作为面向对象三大特征之一,多态的官方解释是同一种事物在不同时刻所表现出的不同状态。
多态的存在条件有一下三个方面:
1.必须具有继承关系,严格地说该应该包括接口的实现,接口的实现与类的继承在本质上是一样的;继承关系是实现多态必不可少地条件.
2.在已具有继承关系的前提下,方法的重写也是重要的前提条件之一;子类根据自身功能需要对父类已有方法进行重写,即覆盖,此处即体现了同一个方法在父类和子类中表现出两种不同的状态
3.最后一点,也是在代码编译,运行阶段很重要的一点,及父类对象的引用指向子类对象,我们也可以将其称为"子类对象的向上转型",既然存在向上转型,那么就一定存在向下转型,关于向上转型与向下转型,我们稍候进行解释
下面这段代码即父类对象的引用指向子类对象
Class Person{}
Class Worker extends Person{
......
}
Class Doctor extends Person{
......
}
Person p1=new Worker();
Person p2=new Doctor();
//此处类Worker,Doctor均是Person的子类,new Worker(),new Doctor()分别创造了两个子类对象,
而p1,p2两个父类引用在此时可以指向两个子类对象
需要注意的是——
此处的父类引用指向子类对象指的是,编译期对象类型是父类,而在代码运行阶段对象类型是子类;以一段代码举例
在上一个代码段基础上,在父类Person中添加方法working(),两个子类分别对父类中的working()方法进行重写,如下:
Class Person{
public void working(){
System.out.println("A Person is working");
}
}
//在子类中对方法进行重写
Class Worker extends Person{
public void working(){
System.out.println("A Worker is working");
}
}
Class Doctor extends Person{
public void working(){
System.out.println("A Doctor is working");
}
}
//父类引用指向子类对象,并进行方法的调用,观察代码运行结果
Person p1=new Worker();
Person p2=new Doctor();
p1.working();
p2.working();
运行结果:
A Worker is working
A Doctor is working
运行结果充分证明了代码运行阶段,对象类型是子类对象,将这个规律可简单归结为一句话——
编译看左边,运行看右边
多态性还可以体现在方法的参数列表上
以一段代码为例
在上面代码段的基础上添加一个方法,命名为function,并创建对象调用该方法如下
public void Function(Person person){
person.working();
}
//创建对象
Person person=new Person();
Worker worker=new Worker();
Doctor doctor=new Doctor();
//调用方法
Function(person);
Function(worker);
Function(doctor);
//运行结果:
A Person is working;
A Worker is working;
A Doctor is working;
观察代码运行结果,不难发现,尽管该方法的参数类型为父类Person,也可以传入Person的任一子类对象,可体现了参数的多态性;以上均为子类对象的向上转型。
向上转型和向下转型与基本数据类型转换原理有些类似,向下转型即父类对象->子类对象的转换,
子类对象可以调用父类所有的非私有方法,而父类对象无法调用子类方法,为了解决这一问题,常常需要将父类对象转化为子类对象,直接进行转换会出现编译错误,需要进行强制转换。
这一过程与大容量基本数据类型-->小容量基本数据类型类似,只不过因为是引用数据类型,所以并不存在精度损失,溢出等问题.
下面是一则综合案例,分别对对象进行向上转型和向下转型.
//向上转型创建Bird对象
Animal animal=new Bird();
animal.eat();
//引入instanceof关键字并向下转型
if (animal instanceof Bird){
Bird bird=(Bird) animal;
bird.fly();
}
fly()方法是鸟类独有的方法,在进行向上转型后无法调用该方法,故引入instance of关键字,并进行向下转型.
进行简单地归纳总结便是:
向上转型是为了提高程序的扩展性
向下转型是为了使用子类中特有的方法