多态的定义:指为不同的数据类型的实体提供统一的接口
多态意味着父类型的变量可以引用子类型的对象
多态的分类:
多态可分为变量多态与函数多态。变量多态是指:基类型的变量,可以被赋值基类型对象,也可以被赋值派生类型的对象。函数多态是指,相同的方法调用形式,传送给一个对象变量,可以有不同的行为。因此,变量多态是函数多态的基础。
多态的三种表现形式:
- 继承
- 重写
- 基类引用指向派生类对象
例如:每条狗狗都是一只动物,但并非每只动物对象都是狗狗。因此,总可以将子类的实例传给需要基类的参数,为不同的派生类提供使用基类方法的统一的接口。
我现在想知道这只动物喜欢做什么,是否需要每次创建一个新对象然后进行判断?
我们根据多态的定义,可以这样实现:
public class demo {
public static void main(String[] args) {
show(new Animal());
show(new Dog());
show(new Pig());
}
public static void show(Animal animal) {
System.out.println(animal.like());
}
}
class Animal {
public String like() {
return "sleep";
}
}
class Dog extends Animal {
@Override
public String like() {
return "play";
}
}
class Pig extends Animal {
@Override
public String like() {
return "eat";
}
}
通过多态,我们便可以实现放入什么动物就可以得知这只动物的喜好,而无需再进行判断。
前面已经提到,多态需要在继承的基础上进行,从案例中我们可以知道多态需要调用并重写基类的方法来实现,所以Dog、Pig类一定要是Animal的子类。
多态的调用:
基类类型 变量名 = new 派生类类型()
1. Animal animal = new Dog(); 其中Dog类向上转型为Animal
2. Animal animal = new Animal();
Dog dog = (Dog)animal;
(Dog)为强制转换,因为Animal对象不一定是Dog对象的实例,所以需要显示转换,告诉编译器 animal就是一个Dog对象。
向上转型:对A的对象的方法的扩充,即A的对象可访问B从A中继承来的和B“重写”A的方法
动态绑定:在上例中,animal 引用使用Dog()创建的对象,所以animal的实际类型为Dog,因此animal.like() 调用的方法为Dog()中的重写方法而不是Animal中的like()方法。这称为动态绑定
instanceof关键字:
instanceof 关键字用来判断父类对象是不是子类的一个实例。
在最开始的例子中,show(new Dog())语句中我们将new Dog()赋值给一个Object类型的参数,但如果Object类型不是Dog类型的一个实例,运行时就会出现异常ClassCastException,所以好的做法是,先判断两者是否为继承关系,确保该对象是另一个对象的实例。
多态中的重写:
为了实现不同数据类型可以共同使用基类的方法,需要对基类的方法进行重写。
重写:在两个类为继承关系时,仅改变函数体,不改变形参和返回值的一种实现。