面向对象的程序设计语言有三大特征:封装,继承,多态。
这次我们就来讲一讲多态。
多态的概念
多态:(以封装和继承为前提)多态体现为父类引用变量可以指向子类对象。
多态现实意义理解:
现实事物经常会体现出多种形态,如学生,学生是人的一种,则一个具体的同学张三既是学生也是人,即出现两种形态。
Java作为面向对象的语言,同样可以描述一个事物的多种形态。如Student类继承了Person类,一个Student的对象便既是Student,又是Person。
多态体现为父类引用变量可以指向子类对象。
前提条件:必须有子父类关系。
多态的实现条件
Java实现多态有三个必要条件:继承、重写、向上转型。
继承:在多态中必须存在有继承关系的子类和父类。
重写:子类对父类中某些方法进行重新定义,在调用这些方法时就会调用子类的方法。
向上转型:在多态中需要将子类的引用赋给父类对象,只有这样该引用才能够具备技能调用父类的方法和子类的方法。
只有满足了上述三个条件,我们才能够在同一个继承结构中使用统一的逻辑实现代码处理不同的对象,从而达到执行不同的行为。
多态的定义与使用格式
定义格式:父类类型 变量名=new 子类类型();
多态的使用
前提:多态对象把自己看做是父类类型
- 成员变量: 使用的是父类的
- 成员方法: 由于存在重写现象,所以使用的是子类的
- 静态成员: 随着类的加载而加载,谁调用就返回谁的
多态例题
package cn.tedu.oop2;
/*本类用于测试多态成员的使用情况*/
public class TestDemo2 {
public static void main(String[] args) {
//7.创建纯纯的子类对象
Dog2 d = new Dog2();
System.out.println(d.sum);//20,子类自己的属性
d.eat();//小狗爱吃肉包子,子类自己的方法
//8.创建多态对象
/*口诀1:父类引用指向子类对象*/
/*口诀2:编译(保存)看左边,运行(效果)看右边*/
Animal2 a = new Dog2();
/*多态中,成员变量使用的是父类的*/
System.out.println(a.sum);//10
/*多态中,方法的声明使用的是父类的,方法体使用的是子类的*/
a.eat();//小狗爱吃肉包子
/*多态中,调用的静态方法是父类的,因为多态对象把自己看作是父类类型
* 直接使用父类中的静态资源*/
a.play();//没有提示,玩啥都行~
Animal2.play();
}
}
//1.创建父类
class Animal2{
//3.创建父类的成员变量
int sum = 10;
//4.创建父类的普通方法
public void eat(){
System.out.println("吃啥都行~");
}
//9.1定义父类的静态方法play
public static void play(){
System.out.println("玩啥都行~");
}
}
//2.创建子类
class Dog2 extends Animal2{
//5.定义子类的成员变量
int sum = 20;
//6.重写父类的方法
@Override
public void eat(){
System.out.println("小狗爱吃肉包子");
}
//9.2创建子类的静态方法play
//@Override
/*这不是一个重写的方法,只是恰巧在两个类中出现了一模一样的两个静态方法
* 静态方法属于类资源,只有一份,不存在重写的现象
* 在哪个类里定义,就作为哪个类的资源使用*/
public static void play(){
System.out.println("小狗喜欢玩皮球~");
}
}
动态绑定
在调用一个方法时,从源代码上看,无法确定调用了哪个对象的方法。只有在程序运行期间根据对象变量引用的实际对象才能确定此方法是哪个对象的。这种现象称之为动态绑定 (联编)。
结论: 动态绑定的前提是:
1) 发生继承,且一个父类有多个子类。
2) 在每一个子类中对继承自父类的同一个方法实现了重写。
3) 发生多态,即: 父类对象变量引用了不同的子类对象。
4) 父类的对象变量调用了重写的方法,即: 发生了动态绑定。从而实现了多的价值。
多态的好处
学习的目的是为了更好地实践,要想在不断进行的项目中可以完成的更好、更为的轻松,这是离不开多态的。我们可以从最后一个demo中,看出加上动态绑定的图形选择,可以很有效的避免我们敲出很多图形的初始化代码,很高效,而且重复的初始化图形,很容易把我们惹毛的(当然这是开玩笑的),而我们要做的就是,尽量减少我们的工作负担,更为高效、轻松的完成。