多态

多态

介绍

一个事物有多种形态,如水有液态固态等。
一个父类下面有多个子类,子类都重写父类的方法。
当子类统一调用父类的方法 ,表达的方式各不相同,这就是多态。

本质:父类的引用指向子类的对象
1、编译类型在=左,运行类型在=右
2、一个对象的编译类型和运行类型可以不一致
但是运行类型至少是编译类型或编译类型的后代

编译时多态和运行时多态

编译时多态体现

  1. 编译时多态主要通过方法重载实现
  2. 重载不仅限于子类

运行时多态

  1. 运行时多态主要通过动态绑定(方法重写)实现
  2. 比如说你用父类接受子类对象(通过父类的引用访问子类重写的父类方法),调用方法的时候确是调用子类的方法,这不就是动态绑定了,在你确定new了哪个对象才知道调用哪个方法

总结

简而言之就是,编译时多态在编译的时候就确定要调用哪个方法了,而运行时多态主要体现了方法的重写实现的

多态的向上转型

语法:父类 对象名 = new 子类
本质:父类的引用指向子类的对象
可以理解成:向上转型在可以调用父类(编译类型)的所有可调用的方法(包括父类以及祖先类的方法),运行判断子类是否重写
规则:
1、向上转型不能调用子类的特定成员(方法和属性)(一般调用子类重写方法)
补充:编译器会把你理解成编译类型,而不是运行类型
2、向上转型的属性调用是编译类型的属性,属性没有重写
运行时:调用方法从前子类一直向父类查找是否有此方法,先在那找的运行那的方法(后面就不找了)
从子类(运行类型)开始查找方法
补充:当通过运行类型的构造方法传值进来。无指定的情况下,看子类是否有变量接收,如果没有看父类是否有变量接收

多态的向下转型(容易报错)

语法:子类类型 对象名 = (子类类型) 父类引用
可以理解成:向上转型后需要调用子类特定方法,这时就需要向下转型
把父类引用改成子类类型
需要本身是父类引用指向子类类型,才可以向下转型
本质:
1、只能强转父类的引用,不能强转父类的对象
2、要求父类的引用必须指向的是当前目标类型的对象
3、可以调用子类类型中所有的成员
补充:
父类类型 对象名 = (父类类型) 爷类引用
是没有问题的

多态数组

多态数组:在引用类型的数组中,采用多态的形式保存对象
简单来说就是创建一个父类类型数组,让每个元素可以保存不同的子类对象
我在Person抽象类中声明一个eat抽象方法,
XiaoMing和XiaoZhang类继承Person抽象类并重写了eat抽象方法。

先创建向上转型的对象,在数组创建时传入对象
Person xiaoMing = new XiaoMing();
Person xiaoZhang = new XiaoZhang();
Person[] person = {xiaoMing,xiaoZhang};
//吃饭
person[0].eat();
person[1].eat();
在数组创建时进行创建并传入数组向上转型的对象
Person[] person = {new XiaoMing(),new XiaoZhang()};
//吃饭
person[0].eat();
person[1].eat();

先创建数组,后进行赋值

Person[] person = new Person[2];
person[0] = new XiaoZhang();
person[1] = new XiaoMing();
for (int i = 0;i < person.length;i++){
    person[i].eat();
}

执行上面三个代码块后,输出的结果都是两个子类重写的方法
file