目录
2.子类属于父类,却又不同于父类;或者说相同的所属不同的表现形态(多态)
理解要点:
-
理解面向对象编程的三大特点:封装、继承、多态
-
理解多态的定义:即同一类的不同对象,对同一事件作出不同反应(不同状态)。
-
参考链接:java多态性理解
本文撰文环境:
-
本文基于windows10(1803)
-
本文编译环境:jdk11(未使用jdk11特性)
-
本文使用eclipse版本-Version: 2018-12 (4.10.0)
本文开始:
一、什么情况才算多态?
也许你不知道多态的定义,那么我们直接从生活例子代码中来理解多态吧。
动物类下面有猫科类、人类、猴类。如果让这些不同的动物面对高大桃树上的成熟桃子会分别有怎样的表现?
答案可能是:
-
一只猴子来到树下,猴子一看见桃子就迅速的就爬上桃树树梢,就去摘桃子吃了.........
-
一个人来到桃树下,他没有猴子那么能爬树,就借助工具来摘桃子,而与猴子达到相同的目的........
-
一只猫来到桃树下,猫看见有一颗高大的桃树,这只猫就爬上树,找个结实的树杈上睡觉去了.........
这里,猴类、人类、猫类,都是是动物一类,为什么他们就做出的不同的反应或行为?猴类、人类、猫类就是一个类(父类)的不同实现类(子类),这些动物们面对同一事物所作出的不同反应、行为、态度。在面向对象编程的编程语言中称之为多态。
再比如说一个生活中的例子,电脑的F1键,在windows中是帮助按钮。在操作打印机的时候是打印按钮,在linux中是搜索按钮,这里描述的都是F1按钮,但是F1在不同的地方是有不同反应的,这也是多态的列子
二、用代码来描述多态
有一个动物类(Animal、父类类),他是所有动物的抽象定义类,比如动物会宏观运动----就是我们肉眼看见的会移动的物体。动物类下面有猫科类、人类、猴类、鼠类等等。
父类Animal(动物类):
/**
* 该类定义了什么是动物,以及动物都有哪些特征,比如动物都会吃东西,会宏观移动等等
**/
public class Animal {
//定义动物的属性,即什么称之为动物的定义。这是动物一类贴上的标签。无法更改,也无法删除
final String AnimalCharacteristics = "会宏观移动的物体就是动物";
/**
* 让动物这一类抽象自己说自己的定义是什么的方法体(控制台输出就是说),这定义是概括性的
*/
public void sayWhatIsAnimal() {
System.out.println(AnimalCharacteristics);
}
/**
* 该方法表示动物看见什么或者感应到什么所作出的反应,动物类也作出了一个概括性的回答(控制台输出就是回答)。
* 比如如果动物感受到一个高大的树,动物会做出什么样的反应,就做出了一个概括性的回答
*
* @param thing 感受到的事物
**/
public void see(String thing) {
if (thing.equals("一颗高大的树")) {
System.out.println("不同的动物有看见一棵树有不同的表现形式哦,如果是猴子看见了数就会往上爬,如果是猫的话就会上去睡觉哦");
} else {
System.out.println("不同的动物看见相同的事物有不同的表现哦,比如猴子看见长着成熟桃子的桃树与人类看见这种桃树所作出的行为是不一样的哦");
}
}
/**
* 该方法回答了表示动物一类都是怎么吃东西的,这个回答都是概括性的(这个回答就是控制台输出)
**/
public void eat() {
System.out.println("不同的动物有不同的吃法。例如我的子类--猫猫狗狗、猿类、人类都是是使用嘴吃饭的");
}
/**
* 该方法回答了表示动物一类都是怎么移动的,这个回答都是概括性的(这个回答就是控制台输出)
**/
public void move() {
System.out.println("不同的动物有不同的移动方法,会宏观移动也是动物的特征啊");
}
}
继承了动物(Animal、父类)类的下属类猫(cat、Animal子类)、鼠类(Mouse、Animal子类)。子类虽然可以拥有父类的一切方法和属性,但是如果没有重写父类的方法的话,也不算动物类(Animal父类)的多种存在形态了。也就是说如果子类不重写父类方法就不算多态。
/**
* 该类是动物类的子类---猫类,猫是动物, 所以猫有动物的属性,即猫是会宏观移动的事物, 猫会吃东西,猫会移动,猫也能感受到信息(通过眼睛感受)
*
*/
class cat extends Animal {
final String catName = "tom";
/**
* 重新定义了动物类的感受事物的方法(see)。
*
* @param thing 一个能感受到的事物
*/
@Override
public void see(String thing) {
if (thing.equals("一颗高大的树")) {
System.out.println("我是猫,我要爬上去睡一个舒服的懒觉,我晚上还要值班呢!");
}
}
/**
* 这是一个猫特有的感受事物的方法:如果猫看见老鼠的方法
*
* @param ms 如果猫看见老鼠的会做什么
*/
public void see(Mouse ms) {
if (ms.MouseName.equals("Jerry")) {
System.out.println("我是" + catName + "猫(动物),今天我看见了老鼠(动物)" + ms.MouseName + ",今天我要捉住它!!");
} else {
System.out.println("我是" + catName + "猫(动物),今天我看见了老鼠,可惜我不认识它,但是我还是要把它捉住");
}
}
/**
* 这是tom猫(动物)要吃老鼠老鼠的时候
*
* @param ms 传入一个老鼠类
*/
public void eat(Mouse ms) {
if (ms.MouseName.equals("Jerry")) {
System.out.println("哇,是老鼠!还是杰瑞哦,我天生就是吃杰瑞老鼠的动物");
} else {
System.out.println("哈,居然不是杰瑞,我就喜欢吃杰瑞老鼠,不是杰瑞我不吃");
}
}
}
/**
* 继承了老鼠这个类别的老鼠类。老鼠属于动物这个类别
*
*/
class Mouse extends Animal {
// 这只老鼠有个名字叫杰瑞
final String MouseName = "Jerry";
}
此时我们大概可以理解多态、继承的含义了吧。
以上代码体现了一个父类(Animal),下属有很多子类(Cat、Mouse......)的从属关系,这些子类同时都继承了父类的属性。比如动物的特征(Animal.AnimalCharacteristics)、动物会宏观上的移动行为(Animal.move())。
但是,猫(cat)、老鼠(Mouse)等都是动物类(Animal)的不同形态而已,但他们还只是一个定义,不管他们谁是谁的子类别,谁是谁的父类别,他们(cat、 mouse、Fish......等等)都还只是一个定义而已,仍然不可以被运用(在计算机中是指被执行)。所以还不是对象(不是一个活着的、可以运行的事物)
三、什么是对象
在IT行业中,对象是于该类(代码片段)在计算机中是指能不能被使用,能不能被调用,能不能被计算机这个数字世界中奔跑的、可以执行的代码。所以以上代码都还只是类,不能算作对象。在java中通过new这个关键词来实现对类的调用,也就是让这个类活起来,将类变成可以被计算机执行、调用,可以在计算机的数字世界中奔跑的代码或程序,那时候才算对象
所以我们通过new关键词,让这些动物活起来,可以在计算机中被调用,被执行吧:
class AnimalMain {
public static void main(String[] args) {
/** 猫对象激活。就通过new这个关键词来实现对象的激活,在没有被new之前,
*它只是一个类,还不算一个对象哦,也就是不是一个可以被任意调用的代码块
*我们现在要让这个被定义的类活过来的方法就是荣国new的关键词
*/
cat ca = new cat();
// 创建一只老鼠的对象
Mouse ms = new Mouse();
// 如果让猫看见一颗高大的树,这只猫会怎么做?
ca.see("一颗高大的树");
// 如果让猫看见杰瑞这个对象呢
ca.see(ms);
// 如果让猫移动呢
ca.move();
}
}
以上运行的结果输出(如果对输出结果还有疑问,请继续看第四节、面向对象编程特征):
我是猫,我要爬上去睡一个舒服的懒觉,我晚上还要值班呢!
我是tom猫(动物),今天我看见了老鼠(动物)Jerry,今天我要捉住它!!
不同的动物有不同的移动方法,会宏观移动也是动物的特征啊
四、面向对象编程特征
在类的继承继承中。如果子类没有重写父类方法的情情况出现的话。就是我们刚刚在定义cat(猫)类的时候,并没有写关于猫类(cat)的移动方法,为什么还会能调用猫类的move()(移动)方法呢?
1.子类可以使用父类方法也可以修改父类方法(继承)
以上代码中,猫(cat)类没有写,也没有重写Animal的move()方法,却能调用move方法,就是因为cat继承了Animal(动物)类,所以cat也可以使用动物的移动(move())方法,这也就说明了继承的特性一。
2.子类属于父类,却又不同于父类;相同的所属,不同的表现形态(多态)
子类(cat、mouse、fish)虽然属于父类(animal),但是子类可以调用父类的方法(通过super关键词),也可以重新构造父类(Animal)的方法(方法重写--Override)。这使得父类之间相互关联(子类继承了父类的属性方法),又彼此互不相同(子类可继承父类方法,也可修改父类方法---大多数情况需要修改父类方法)。
3.每一个类别(子类、父类)都有不可修改性和特殊性(封装)
每一个类之所以成为独特的一类,是因为它有不可更改替代的特殊性,就像他们不可以合成为一个对象一样。所以用来区别父类与子类之间的特殊性的关键词就出现了。即一个该类的属性是一个类别不可修改、用于区分它们与同级类别之间的区别的关键词。就像我们在cat类中使用"private final"定义这只猫的名字一样。这是这个类所特有的,不可以修改的特征,这就是封装。
五、java的面向对象编程:"瘦身"与"变胖"
java中的面向对象编程还有一个额外的特性,就是类别的转型。
1.迷之java:类型的转换
引用1:java转型(向上或向下转型)
其实很好理解,连接中的这些代码都是比较简单的。
2.在不经意之间的类型转换
参考链接:面向对象的特征----自动类型转换(向上类型转换)
class numberExtends {
public static void main(String[] args) {
//不报错,但是被默认转换成了long类型的整数
doubleInput((int) 2);
}
public static void doubleInput(long number) {
System.out.println("you input number is :" + number);
}
}
这里代码编辑其实就是int类型的对象,自动转换成了long类型的数据类型(向下或者向上不清楚)。