多态:对象的多种形态
在程序中的体现表现在:父类的引用或者接口的引用指向了子类的对象
class Animal{
public void eat(){
//int num=0;
System.out.println("food");
}
}
class Dog extends Animal{
//int num=1;
public void eat(){
System.out.println("meat");
}
public void bark(){
System.out.println("汪汪");
}
}
class Monkey extends Animal{
//int num=2;
public void eat(){
System.out.println("banana");
}
}
public class duo {
public static void main(String[] args) {
Animal a=new Dog();//向上转型,隐藏子类型,提高扩展性
Animal b=new Monkey();
method(a);
method(b);
}
private static void method(Animal a) {//定义共性类型的参数,既可以接受a,也可接受b,便于封装,写其他方法
a.eat();
//System.out.println(a.num);
//a.bark();//编译不通过
/*if(a instanceof Dog){
Dog aa=(Dog)a;
aa.bark();
}*/
}
}
运行结果
meat
banana
当面对共性类型时,所有的子类对象都可以接受,优点:提高了代码的扩展性
弊端:不能使用子类的特有方法,否则编译不通过
前提:1.必须有关系(继承,覆盖)
2.通常有覆盖
如果Dog类和Monkey类没有对Animal中的eat方法重写,运行结果会变成
food
food
什么时候向上转型?
如果不需要面对子类对象,使用父类的功能就可以完成操作(子类如果对功能重写,则输出结果是子类方法中的结果),就使用向上转型
如果想使用子类的特有功能?
可以向下转型。但是容易发生classCastException,只要转换类型和对象类型不匹配就会发生类型错误,所以需加类型判断
if(a instanceof Dog){
Dog aa=(Dog)a;
aa.bark();
}
多态中对成员的调用(当子父类中出现同名变量时)
1.成员变量
当子父类中出现同名变量时,多态调用,只看引用变量所属的类。无论编译或运行都看等号左边
如上System.out.println(a.num);的运行结果是0 而不是1or2
2.成员函数
当子父类中出现同名函数时 ,多态调用,编译看的是引用变量所属类的方法,运行时看的是对象所属类的方法。编译看左,运行看右
3.静态函数
出现一模一样的静态函数时,多态调用,只看引用变量所属类的方法。无论编译或运行都看等号左边
真正调用静态方法是不需要对象的,直接类名.函数名()