作者名:编程界明世隐
简介:CSDN博客专家,从事软件开发多年,精通Java、JavaScript,博主也是从零开始一步步把学习成长、深知学习和积累的重要性,喜欢跟广大ADC一起打野升级,欢迎您关注,期待与您一起学习、成长、起飞!
【1】Java小游戏(俄罗斯方块、飞机大战、植物大战僵尸等)
【2】JavaWeb项目实战(图书管理、在线考试、宿舍管理等)
【3】JavaScript精彩实例(飞机大战、贪吃蛇、验证码等)
【4】Java小白入门200例
【5】从零学Java、趣学Java
【6】Idea从零到精通
群里有个小伙伴请我写一篇关于面向对象的文章,起初我也是没有直接答应的,其一是因为最近有点忙,其二是我怕写不好,毕竟面向对象这个点所涉及的内容范围广。
我也是酝酿了好几天,才把这个文章写出来,希望对小伙伴们理解面向对象有一些些帮助,也希望我的那位粉丝朋友能够从这篇文章中得到他想要的知识。
面向过程,就是先把要解决问题的步骤分析出来,然后一步步的去实现,再一个个去调用。
面向对象,是把解决问题分解成多个对象,而对象是描述处理某些问题的一种行为。
这样简单描述一下,肯定是有点没搞明白,下面举些生活中的例子来说明。
生活中的例子:你想吃脐橙
面向过程举例:
出门–>坐车–>超市–>挑选脐橙–>付钱–>坐车回家–>拿出脐橙–>剥脐橙–>吃脐橙–>洗手。
这里简单描述了从买脐橙到吃脐橙的一个过程,面向过程就是把上面每个步骤用不同的方法来实现。
面向对象举例:
面向对象的设计则是从另外的思路来解决问题,如下:
我要吃脐橙–>女朋友把脐橙拿到你面前–>吃。 完事
分析一下,女朋友要做哪些事情:
出门–>坐车–>超市–>挑选脐橙–>付钱–>坐车回家–>拿出脐橙–>剥脐橙–>喂你–>洗手。
这是肯定会有小伙伴说了,你这跟面向过程并没有区别呀,这是动作只是分成了2个人去完成而已,并没有减少或者优化什么。
表面上看起来确实是这样的,但我们可以透过问题看本质:
出门–>坐车–>超市–>挑选脐橙–>付钱–>坐车回家–>拿出脐橙–>剥脐橙–>吃脐橙–>洗手,周而复始。
于是明哥我就问你,你听懂了吗?如果没听懂,那我就没辙了。
对象就是存在的具体实体,具有明确定义的状态和行为,是面向对象编程的核心,用来描述现实世界中的实体,为计算机应用程序提供实体基础,也是完成特定任务一个封装。
封装最好理解了。封装是面向对象的特征之一,是对象和类概念的主要特性。
封装,也就是把客观事物封装成抽象的类,并且类可以把自己的数据和方法只让可信的类或者对象操作,对不可信的进行信息隐藏。
通俗来说,你的女朋友你调用”我要吃脐橙“方法,你可以吃到脐橙,别人也可以调用他的女朋友对象的”我要吃脐橙“方法,而你能否调用”别人“女朋友”的 “我要吃脐橙”方法?答案显然是不可以的。
也就是说类是一个抽象的集合,在这里“女朋友”抽象成类。
而对象是一个独立的个体,比如你的女朋友,他的女朋友;她们都是“女朋友”,但她们又是相互独立没有关系的。
public class GirlFriend {
String name;//名字
int age;//年龄
}
测试一下:
public class Test {
public static void main(String[] args) {
GirlFriend girlFriend = new GirlFriend();
girlFriend.name="蔡文姬";
System.out.println("我的女朋友:"+girlFriend.name);
}
}
运行结果:
我的女朋友:蔡文姬
public class GirlFriend {
private String name;//名字
private int age;//年龄
}
此时我们再看测试类,是报错的
于是我们可以将赋值和取值封装成方法。
public class GirlFriend {
private String name;//名字
private int age;//年龄
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
测试调用:
public class Test {
public static void main(String[] args) {
GirlFriend girlFriend = new GirlFriend();
//girlFriend.name="蔡文姬";
//System.out.println("我的女朋友:"+girlFriend.name);
girlFriend.setName("蔡文姬");
girlFriend.setAge(18);;
System.out.println("我的女朋友:"+girlFriend.getName()+","+girlFriend.getAge()+"岁");
}
}
调用:
我的女朋友:蔡文姬,18岁
public GirlFriend(String name,int age){
this.name=name;
this.age=age;
}
测试代码
public class Test {
public static void main(String[] args) {
GirlFriend girlFriend = new GirlFriend("蔡文姬",18);
// girlFriend.setName("蔡文姬");
// girlFriend.setAge(18);
System.out.println("我的女朋友:"+girlFriend.getName()+","+girlFriend.getAge()+"岁");
}
}
运行结果:
我的女朋友:蔡文姬,18岁
GirlFriend girlFriend = new GirlFriend(“蔡文姬”,18);
都使用了上述代码来创建了一个 girlFriend ,但是每次都其实不是同一个“女朋友”。
代码验证一下:
public class Test {
public static void main(String[] args) {
/* GirlFriend girlFriend = new GirlFriend("蔡文姬",18);
// girlFriend.setName("蔡文姬");
// girlFriend.setAge(18);
System.out.println("我的女朋友:"+girlFriend.getName()+","+girlFriend.getAge()+"岁");
*/
GirlFriend girlFriend = new GirlFriend("蔡文姬",18);
GirlFriend girlFriend1 = new GirlFriend("蔡文姬",18);
System.out.println(girlFriend.hashCode());
System.out.println(girlFriend1.hashCode());
}
}
运行结果:
366712642
1829164700
从输出可以看到,不是同一个对象,我可以这样改:
public class GirlFriend {
private String name;// 名字
private int age;// 年龄
private String manName;// 男人的名字
public String getManName() {
return manName;
}
public void setManName(String manName) {
this.manName = manName;
}
public GirlFriend(String name, int age,String manName) {
this.name = name;
this.age = age;
this.manName = manName;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
测试代码:
public class Test {
public static void main(String[] args) {
GirlFriend girlFriend = new GirlFriend("蔡文姬",18,"我");
GirlFriend girlFriend1 = new GirlFriend("瑶",19,"你");
System.out.println(girlFriend.getManName()+"的女朋友:"+girlFriend.getName()+","+girlFriend.getAge()+"岁");
System.out.println(girlFriend1.getManName()+"的女朋友:"+girlFriend1.getName()+","+girlFriend1.getAge()+"岁");
}
}
运行结果:
我的女朋友:蔡文姬,18岁
你的女朋友:瑶,19岁
就如之前举例中,你无需关心你“女朋友”是怎么给你弄到橙子的,你只要告诉“她”我要吃橙子,然后等她拿橙子喂你即可。
继承机制是面向对象程序设计不可缺少的关键概念,是实现软件可重用的根基,是调高软件系统的可扩展性与可维护性的主要途径。
在Java中,被继承的类我们称之为父类,也叫基类;继承的类叫子类,也称为派生类或超类;继承是面向对象最显著的一个特性。继承是从已有的类中派生出新的类,新的类能继承已有类的数据属性和行为,当然子类也可以扩展属于自己的新能力。
通俗来说,我们每个人都从父母那里继承来了不少能力,比如:吃饭、喝水、说话、走路、思考等等,也可以扩展自己的能力,比如:学编程、打王者(跑题了)。
在Java中,使用如下的语法实现继承的关系:
class 子类 extends 父类{}
public class Test {
public static void main(String[] args) {
Student student = new Student();
System.out.println(student.age);
}
}
class Human {
int age = 20;//年龄
}
class Student extends Human{
}
运行结果:
20
可以看到 age属性被继承下来了,但是如果 age声明为private的,则无法被继承了。
public class Test {
public static void main(String[] args) {
Student student = new Student();
student.study();
}
}
class Human {
int age = 20;//年龄
void study(){
System.out.println("学习技能");
}
}
class Student extends Human{
}
运行结果:
学习技能
当然也是不能继承父类声明为 private 的成员方法的。
public class Test {
public static void main(String[] args) {
Student student = new Student();
student.study();
}
}
class Human {
int age = 20;//年龄
void study(){
System.out.println("学习技能");
}
}
class Student extends Human{
@Override
void study(){
System.out.println("在学校学习知识");
}
}
运行结果:
在学校学习知识
public class Test {
public static void main(String[] args) {
Student student = new Student();
student.study();
student.pStudy();
}
}
class Human {
int age = 20;//年龄
void study(){
System.out.println("人学习技能");
}
}
class Student extends Human{
@Override
void study(){
System.out.println("在学校学习知识");
}
void pStudy(){
super.study();
}
}
运行结果:
在学校学习知识
人学习技能
super关键字的用法如下:
1、super可以用来引用直接父类的实例变量。
2、super可以用来调用直接父类方法。
3、super()可以用于调用直接父类构造函数。
这里只说明了super可以直接调用父类,其他也比较类似的使用方式。
所谓多态就是指程序中定义的引用变量所指向的具体类型和通过该引用变量发出的方法调用在编程时并不确定,而是在程序运行期间才确定,即一个引用变量倒底会指向哪个类的实例对象,该引用变量发出的方法调用到底是哪个类中实现的方法,必须在由程序运行期间才能决定。
多态是同一个行为具有多个不同表现形式或形态的能力。
public class Test {
public static void main(String[] args) {
Human h = new Student();
h.study();
}
}
class Human {
int age = 20;//年龄
void study(){
System.out.println("人学习技能");
}
}
class Student extends Human{
@Override
void study(){
System.out.println("在学校学习知识");
}
}
运行结果:
在学校学习知识
可能有小伙伴就没看明白了,这和之前得代码不是差不多吗?
其实差别在这里:
Human h = new Student();
h.study();
这里实例的对象是Student,但是向上转型成了Human后,然后通过Human的实例对象来调用study 方法,但其实这个 h 是Student的实例对象,最终调用的是Student的study方法。
Java实现多态有三个必要条件:
继承、重写、向上转型。
继承、重写,本例之前就已经满足了;
Human h = new Student(); 就是向上转型;
多个子类代码
public class Test {
public static void main(String[] args) {
//向上转型
Human h = new Student();
h.study();
//向上转型
Human h1 = new Coder();
h1.study();
//未向上转型
Human h2 = new Human();
h2.study();
}
}
class Human {
int age = 20;//年龄
void study(){
System.out.println("人学习技能");
}
}
class Student extends Human{
@Override
void study(){
System.out.println("学生在学校学习知识");
}
}
class Coder extends Human{
@Override
void study(){
System.out.println("程序员在办公室加班学习编程知识");
}
}
运行结果:
学生在学校学习知识
程序员在办公室加班学习编程知识
人学习技能
看上述代码,在编译时无法区别出他们的不一样,但是运行的时候,结果却截然不同。
可能你会问了,为什么要这么弄呢,搞继承、重写、还要向上转型。
其实在工作中会碰到程序扩展的问题,比如要新加一个学工程的,在这里就很方便了。
public class Test {
public static void main(String[] args) {
//向上转型
Human h = new Student();
h.study();
//向上转型
Human h1 = new Coder();
h1.study();
//未向上转型
Human h2 = new Human();
h2.study();
Human h3 = new Builder();
h3.study();
}
}
class Human {
int age = 20;//年龄
void study(){
System.out.println("人学习技能");
}
}
class Student extends Human{
@Override
void study(){
System.out.println("学生在学校学习知识");
}
}
class Coder extends Human{
@Override
void study(){
System.out.println("程序员在办公室加班学习编程知识");
}
}
class Builder extends Human{
@Override
void study(){
System.out.println("建造者在工地上学习建造");
}
}
这样的扩展就非常的方便,无需要对 Student 和 Coder 的代码做任何的修改,在日常开发中,往往 Student 和 Coder类的代码很复杂,一个不小心会导致一些错误,从而给我们的编码工作带来一些困扰。
当然基于接口实现的多态是工作中更为常见的,其原理和上述基本一致,这里就不再说明了。
以上就是我的浅见了,大家觉得还行的话,给明哥来个三连吧!
【1】Java小游戏(俄罗斯方块、飞机大战、植物大战僵尸等)
【2】JavaWeb项目实战(图书管理、在线考试、宿舍管理等)
【3】JavaScript精彩实例(飞机大战、贪吃蛇、验证码等)
【4】Java小白入门200例
【5】从零学Java、趣学Java
【6】Idea从零到精通