多态(polymethod)
说明:多态是建立在封装和继承的基础之上的
为什么需要多态?
代码的复用性不高,不利于维护
举例:人给动物喂食这个方法,如果动物和添加了,那事物也需要添加,那必然会造成需要不断地添加方法,就会造成代码的复用性不高
多态的体现
一、方法的多态
同类中方法的重载和继承关系中==方法的重写(覆盖)==体现多态,虽然都是同一个方法,但是可以以一定的规则调用不同的方法,提高了代码的复用性
二、对象的多态(核心,困难,重点)
-
一个对象的编译类型和运行类型可以不一致
-
编译类型在定义对象时,就确定了,不能改变
-
运行类型是可以变化的
-
编译类型看定义时 = 号的左边,运行类型看 = 号的右边
总结:多态的体现就在于父类的引用(编译类型)可以接收(指向)子类的对象(运行类型),这样的好处在于方便统一管理,无需重复编写代码
多态的使用细节
-
多态的前提是:类之间存在继承关系
-
向上转型
-
(1)语法:父类类型 引用名 = new 子类类型();
-
(2)特点:编译类型看左边,运行类型看右边。
-
(3)可以调用父类中的所有成员(需要遵守访问权限限制),不能调用子类中特有的成员(能够调用哪些内容是由编译类型所决定的)。
-
(4)最终运行效果看子类的具体实现
-
向下转型
-
(1)语法:子类类型 引用名 = (子类类型) 父类引用;
-
(2)只能强转父类的引用,不能强转父类的对象
-
(3)要求父类的引用必须指向的是当前目标类型的对象
-
(4)当向下转型后,可以调用子类类型中所有的成员
-
补充:调用的时候优先在本类中找,如果没有就找到父类(直到Object)
代码示例
package poly;
public class animal {
public void run(){
System.out.println("调用animal类中的---run()方法");
}
public void eat(){
System.out.println("调用animal类中的---eat()方法");
}
public void show(){
System.out.println("调用animal类中的---show()方法");
}
public void get(){
System.out.println("调用animal类中的---get()方法");
}
}
package poly;
public class cat extends animal{
public void run(){
System.out.println("调用cat类中的---run()方法");
}
public void eat(){
System.out.println("调用cat类中的---eat()方法");
}
public void show(){
System.out.println("调用cat类中的---show()方法");
}
public void print(){
System.out.println("调用cat类中的---print()方法");
}
}
package poly;
public class main {
public static void main(String[] args) {
animal animal = new cat();
animal.eat();
animal.run();
animal.show();
animal.get();
cat cat = (cat)animal;
cat.print();
}
}
调用cat类中的---eat()方法
调用cat类中的---run()方法
调用cat类中的---show()方法
调用animal类中的---get()方法
调用cat类中的---print()方法
特别注意!!!
Java 中,子类引用不可以指向父类,但是父类引用可以指向子类,这是由于继承关系的特性
一、 父类引用指向子类对象
-
父类引用可以指向子类对象,因为子类是父类的扩展(除了拥有父类的内容以外,子类可以拥有自己的内容,但是父类不会拥有),子类对象是父类类型的一个实例。
-
这时,父类引用只能访问父类中的方法和属性,不能访问子类特有的方法和属性(除非进行类型转换)。
二、子类引用不能指向父类对象:
-
子类是父类的扩展,子类中可能有父类没有的属性和方法,编译器无法保证子类引用指向父类对象时访问的安全性。
-
如果强行让子类引用指向父类对象,编译器会报错,除非进行强制类型转换并且确保类型安全(通过instanceof检查等方式)。