一、多态
在了解多态之前我们先了解以下以下的知识点
1. 向上转型
解释: 把子类对象赋值给了父类对象的引用
我们通常实例化一个对象,都是写的这种形式:Dog a = new Dog( );,用相同类型的引用实例对象。而此时代码写成Animal a = new Dog( );,就称之为向上转型。(Animal是Dog的父类)
这种写法都叫“向上转型”,将子类对象的引用赋值给了父类的引用,如
语法原则
代码形式:
引用类型 a =new 对象类型();
子类对象可以赋值给父类对象的引用,对象类型可以是引用类型的子类
下列代码说明多态的语法是怎样?
- 只能对引用调用其引用类型中声明的方法
- 运行时,根据对象类型调用子类覆盖后的方法
从空间角度:
2.方法的覆盖
上一篇文章讲过,这里补充的是它的别名还可以称为覆写/重写/覆盖(Override)。
原则如下:(其中关键字final和static后面学习)
重写与重载的区别:
1.重写实现的是运行时的多态,而重载实现的是编译时的多态。
2.重写的方法参数列表必须相同;而重载的方法参数列表必须不同。
3.重写的方法的返回值类型只能是父类中的父类类型与子类中的子类类型或者跟父类中被重写的方法返回值相同,而重载的方法对返回值类型没有要求。
3.向下转型
向上转型是子类对象转成父类对象, 向下转型就是父类对象转成子类对象。相比于向上转型来说, 向下转型没那么常见,但是也有一定的用途。
强制转换原则:
1)向下转型需要使用强制类型转换,不然会失败
2)(Dog) a:表示强制类型转换,但是这样的向下转型有时是不太可靠的,也不太安全。”抛出异常”
3)没有继承关系的两个类的引用之间,不能赋值,即使强转也不行。
instanceof关系运算符
instanceof 可以判定一个引用是否是某个类的实例,如果是, 则返回 true;这时再进行向下转型就比较安全了。
换句话说, instanceof关系运算符是判断引用中的对象和类名是否兼容,用在强制转换前,避免类型转换失败(抛出异常)。
animal 本质上引用的是一个 Cat 对象, 是不能转成 Dog对象的,下面就不会执行了:
Animal a = new Cat("小猫");
if (a instanceof Dog) { //a引用中对象 是不是Dog false
Dog d = (Dog)a; //a引用中对象 是不是cat ture
d.shout(); //a引用中对象 是不是animal ture
}
所以代码不执行,就不会出现抛出异常这种错误
动态绑定与静态绑定
动态绑定也称为运行时绑定。静态绑定也有编译时绑定的说法。为什么会有这种说法呢?
运行时多态是发生在重写之上的,它们的代码都相同,但是表达的侧重点不同。
相反,编译时绑定就是跟重载相对应的。满足重载时调用其中的某个方法是根据传入的参数判断调用哪个方法,而我们再用相同的命令去查看反编译时而最后调用的也是该方法。因此称为编译时绑定。
二、理解多态
满足多态最基本要求
更简单的说,多态就是一个引用能表现出多种不同的形态
而多态是一种思想,实现它的前提有两点:一是向上转型 ,二是调用同名的覆盖方法。
向上转型的形式
向上转型的形式三种
1) 直接赋值 :上面举的例子中直接用父类引用引用子类对象。
2) 方法传参 :将子类引用传给父类引用作为参数来接收。
3) 方法返回 :将子类的引用传回给类型为父类的引用
多态应用
可以将不同的子类对象统一放到父类数组中,屏蔽了不同子类差异
修改为:
多态优点
3)可扩展能力强
如果要新增一种新的形状, 使用多态的方式代码改动成本也比较低。
对于类的调用者来说, 只要创建一个新类的实例就可以了, 改动成本很低。