如果一个类实现一个接口,那么这个类的对象就呈现出接口数据类型的特点。对象采用接口形式的这种能力就是多态的一个例子。
下面我演示接口如何影响多态的示例。我将使用具有一个父类和实现一个接口的Dog类。定义一个哺乳动物类Mammal,该类将作为Dog类的父类。
/**
* Mammal 类,代表哺乳类动物
*/
public class Mammal {
public void breathe(){
System.out.println("哺乳类动物在呼吸");
}
}
定义一个Play接口,表示追赶和捕捉的对象,它被Dog类来实现:
/**
* 接口中定义了追赶和捕捉的行为
*/
public interface Play {
/**追赶*/
public void playFetch();
/**捕捉*/
public void playCatch();
}
再定义一个Dog类来继承Mammal类并实现Play接口:
/**
* Dog类,代表狗,继承哺乳动物类,并实现了Play接口
*/
public class Dog extends Mammal implements Play {
public void playFetch(){
System.out.println("狗正在追赶");
}
public void playCatch(){
System.out.println("狗正在捕捉");
}
public void sleep(){
System.out.println("狗正在睡觉");
}
}
接下来,我指出Dog对象能够采取的各种形式。通过多态,Dog类能够采取下列形式:
Dog:Dog对象采用的形式当然是Dog;
Mammal:一个Dog对象是一个哺乳动物对象,因为Dog类继承了Mammal类;
Play:一个Dog对象是一个Play对象,因为Dog类实现了Play接口;
Object:一个Dog对象是一个Object对象,因为Dog继承了Mammal类,而Mammal类又继承了Object。
因此,下面的四种语句都是有效的:
Dog fido = new Dog();
Mammal rover = new Dog();
Play spot =new Dog();
Object pooch = new Dog();
这四个Dog对象在内存中看上去都是一样的。然而,它们却是根据其引用不同,使用不同的表现形式。例如,Dog引用fido,不需要任何类型转换就能够调用Dog类、Mammal类、Object类和Play接口中的方法:
fido.sleep();
fido.playFetch();
fido.breathe();
fido.toString();
Mammal类型的引用rover。在没有类型转换的情况下,rover可以调用哪些方法呢?除了Object对象的方法,仅有breathe()方法能够被调用:
rover.breathe();
同样的,在没有类型转换的情况下,Play类型的引用spot能够调用什么方法(除了Object对象的方法)呢?由于spot是Play接口类型的引用,有两个方法可以被调用:
spot.playCatch();
spot.playFetch();
而Object类型的引用pooch仅能调用Object对象中的方法。例如:
pooch.toString();
如果pooch要调用Mammal、Play或Dog类中的任何一个方法,就需要进行强制类型转换。又例如:
((Dog)pooch).sleep();
最后,FourDogs程序演示了Dog对象通过多态来呈现这四种不同的表现形式:
/**
* FourDogs类,演示接口多态
*/
public class FourDogs {
public static void main(String[] args) {
System.out.println("实例化四条狗");
Dog fido =new Dog();
Mammal rover =new Dog();
Play spot =new Dog();
Object pooch =new Dog();
System.out.println("调用Dog的方法");
fido.sleep();
fido.playFetch();
fido.breathe();
System.out.println("fido is"+fido.toString());
System.out.println("\n调用Mammal的方法");
rover.breathe();
System.out.println("\n调用Play的方法");
spot.playCatch();
spot.playFetch();
System.out.println("\n调用Object的方法");
System.out.println("pooch is"+pooch.toString());
((Dog)pooch).sleep();
}
}