为了使方法具有通用型,比如动物叫的方法,因为动物叫声的不同,可以在方法中设置一个接收动物类型的参数。
当传入猫类对象时,发出猫叫声,当传入犬类对象时,发出犬类叫声。
在同一个方法中,如上这种由于参数类型的不同而导致运行结果不同的现象就是多态。
在Java中,为了实现多态,允许使用一个父类类型的变量来引用一个子类类型的对象,根据被引用子类对象特征的不同,得到不同的运行结果
//定义接口Animal
interface Animal {
void shout(); //定义抽象shout方法
}
//定义Cat类实现Animal接口
class Cat implements Animal {
//实现shout方法
public void shout(){
System.out.println("喵喵...");
}
}
//定义Dog类实现Animal接口
class Dog implements Animal {
//实现shout方法
public void shout(){
System.out.println("汪汪...");
}
}
//定义多态测试类
public class Polymorphic {
public static void main(String[] args){
Animal an1 = new Cat(); //创建Cat对象,通过Animal父类类型的变量an1引用子类类型的对象
Animal an2 = new Dog(); //创建Dog对象,通过Animal父类类型的变量an2引用子类类型的对象
animalShout(an1); //调用animalShout()方法,将an1作为参数传入
animalShout(an2); //调用animalShout()方法,将an2作为参数传入
}
//定义静态的animalShout()方法,接收一个Animal类型的参数
public static void animalShout(Animal an){
an.shout(); //调用实际参数的shout()方法
}
}
如上,代码的第24、24行调用animalShout()方法,将父类引用的两个不同子类对象分别作为参数传入,解决了方法同名的问题。
-
注意:new关键字接的是什么,就是创建的哪个对象,如上就是分别创建的Cat子类对象和Dog子类对象。
-
另外子类对象的实例可以用父类对象变量甚至接口变量来引用,如上Cat对象和Dog对象的实例就通过an1和an2变量来引用。可以理解为:
Cat cat = new Cat();
Animal an1 = cat;
其中cat是实例对象,而an1是变量。这里an1变量的实际值为cat,所以当传参数进入animalShout()方法时,通过实际参数调用的的shout()方法其实是cat实例对象的方法,也就是Cat()子类的方法。
-
现实中常见的写法:
Map map = new HashMap();
List list = new ArrayList();
其中Map与List都是接口,HashMap与ArrayList都是实现接口的实现类,Java中允许这样定义。
-
由此可见,继承是多态得以实现的基础。
另外需要注意的是
Animal an1 = new Cat();
此种将子类对象当做父类类型使用的情况,在Java中叫做向上转型。
将子类对象当做父类使用时不需要任何显示地声明,但是,此时不能通过父类变量去调用子类中的特有方法。只能使用父类和子类所共有的方法,其实也就是父类有的方法。
除了向上转型,还有向下转型,他们都是对象的类型转换。下节作详细解释。