前言
在没有接触多态以前,我们在主函数调用方法和属性时,一般是通过对象实例化相应的类来实现的,这十分复杂繁琐,特别是在以后如果遇到一个父类的子类非常的多,那工程量就十分的庞大!因此多态的作用与地位就显得十分的重要。
一.多态的定义
“一个接口,多种实现”——多态是一种性质
方法或对象具有多种形态。多态(polymorphism)指为不同数据类型的实体提供统一的接口。多态允许将子类的对象当作父类的对象使用,父类的引用指向其子类的对象,调用的方法是该子类的方法。多态是建立在继承和封装之上的。
二.多态的作用
1.不必编写每一子类的功能调用,可以直接把不同子类当父类看,屏蔽子类间的差异,提高代码复用性
2.父类引用可以调用不同子类的功能,提高了代码的扩充性和可维护性
三.多态的体现
1.方法重载是一个类中的多态性表现,方法重写是子类与父类的一种多态性表现。
2.实例化对象的过程中也有多态性的体现(以一组继承关系的类来解释Animal是以下动物的父类)
Animal animal=new Dog();
**animal.方法**
animal的编译类型是Animal,运行类型是Dog(这两种类型可以去科普一下,其实理解字面意思就行)
一般“=”左边的是编译类型,右边则是运行类型
这里我们可以通过 父类实例化子类!这样我们就实现了通过一个父类实例化的animal来调用他下属子类的方法,而不再是一一地去实例化子类来调用方法或者传入形参列表,这不极大地提高了代码的复用性吗!
四.多态使用细节
多态的前提是两个对象存在继承关系
1.向上转型
本质:父类的引用指向了子类的对象
父类 引用名 = new 子类类型();
①它可以调用父类中的所有成员(遵守访问权限的前提下)
②不能调用子类中特有的成员
③最终运行效果看子类的具体实现(有继承的性质,调用方法是从子类开始查找)
2.向下转型
本质:用子类的类型来接收父类的实例对象
子类类型 引用名 = (子类类型) 父类引用;
①只能强转父类引用,不能强转父类对象
②要求父类的引用必须指向的是当前目标类型的对象
③当向下转型后,可以调用子类中的所有成员
五.动态绑定机制
当两个类之间存在继承关系,在主函数调用方法时,该方法会和该对象的运行类型(内存地址)绑定起来,例如
我在主函数输入:
Person person =new Boy();
person.run;
输出的是:
boy run
这就很好地说明了动态绑定机制的方式——和运行类型绑定!
六.多态数组
数组与多态相结合,把子类的对象存放在数组单元中,通过遍历数组的过程实现对特定数组元素的统一控制,限定,选择,输出 以及方法的调用
//应用实例:现有一个继承结构如下:要求创建1个Person对象
// 2个Student对象和2个Teacher对象,统一放在数组中,并调用每个对象say方法
Person[] person =new Person[5];
person[0]=new Person("jack",20);
person[1]=new Student("mike",11,90);
person[2]=new Student("jeft",21,70);
person[3]=new Teacher("nick",22,80000);
person[4]=new Teacher("bill",30,60000);
//循环调用多态数组,遍历每个数组元素输出say方法
// person[i]编译类型是 Person,运行类型是是根据实际情况有JVM来判断
for (int i = 0; i < person.length; i++) {
if (person[i] instanceof Teacher) { //判断对象的运行类型是否为Teacher
Teacher teacher=(Teacher) person[i]; //强制转换
System.out.println(person[i].say()); //动态绑定机制
teacher.teach();
}else if (person[i] instanceof Student){
Student student=(Student) person[i];
System.out.println(person[i].say()); //动态绑定机制
student.study();
}else if(person[i] instanceof Person){}
else{
System.out.println("您输入的类型有误!");
}
}```