JAVA:向上转型和动态绑定机制

2020-09-11  本文已影响0人  确认过眼神啊

知识梳理

1.向上转型的概念:
向上转型又叫自动转型、隐式转型.向上转型就是父类引用指向子类实例,也就是子类的对象可以赋值给父类的对象.

Animal dog = new Dog(); // Dog类是Animal类的子类

注:向上转型是安全的,因为任何子类都继承并接受了父类的方法.从例子中也可以理解,所有的狗都属于狗的父类-动物,这是可行的,但是向下转型则不行,若说所有的动物都是狗就不成立.(所以向下转型要通过强制类型转换,后续章节中会将解)
 
2.向上转型的应用
1)当一个子类对象向上转型父类类型以后,就被当成了父类对象,所能调用的方法会减少,只能调用子类重写了父类的方法以及父类派生的方法(如set(),get()方法),而不能调用子类特有的方法.

public class Animal{
   String name;
   int age;
   public Animal(){
    
   }
   public void eat(){
     System.out.println("animal吃东西");
   }

    public static void die(){
            System.out.println("animal死亡");
        }
}
public class Dog extends Animal{
      String favoriteFood;
       public void eat(){
           System.out.println("吃肉");
        }
        public void run(){
            System.out.println("夕阳下奔跑的小狗");
        }
        public static void die(){
            System.out.println("dog死亡");
        }
 }
public static void main(String[] args){
    Animal animal = new Dog();
    animal.age = 2;
    animal.name = "小强";
    animal.favoriteFood = "骨头"; // 访问子类的属性报错
    animal.eat(); // 调用的是子类的方法,输出结果是"吃肉"
    animal.run();// 访问子类特有的方法报错
    animal.die();// 调用的是父类的方法,输出结果是"animal死亡"
}

2)父类中的静态方法时不允许被子类重写的
如父类的有静态方法die()
当子类Dog中也定义同名方法时,此时die()算dog类自己独有的方法:

  Animal animal = new Dog(); // 向上转型
  animal.die();// 调用的是Animal类的die()方法,而不是调用Dog的die()方法
 // 输出结果是:animal死亡

知识扩展

  多态的实现可以通过向上转型和动态绑定机制来完成,向上转型实现了将子类对象向上转型为父类类型,而动态绑定机制能识别出对象转型前的类型,从而自动调用该类的方法,两者相辅相成.
动态绑定:
绑定就是讲一个方法调用同一个方法所在的类连接到一起就是绑定.绑定分为静态绑定和动态绑定两种.

  Chinese c = new Chinese();
  c.speak();
  American a = new American();
  a.speak();
  British b = new British();
  b.speak();

这种调用方式是在代码里指定的,编译时编译器就知道c调用的是Chinese的speak(),a调用的是American的speak().
动态绑定的例子:
如果我们在测试类中做以下改动:

// 生成父类对象数组,数组长度为5
Human[] human = new Human[5];
int n;
for(int i = 0; i < human.length;i++){
  n = (int)(Math.random() * 3); // 随机产生从0到2中的一个数
  switch(n){
    case 0: human[i] = new Chinese();break;
    case 1: human[i] = new American();break;
    case 2: human[i] = new British();break;
  }
}
// 循环输出,循环体中每个对象分别调用speak()方法
for(int i = 0;i < human.length;i ++){
  human[i].speak();
}

此时,Human类中随机生成Chinese类,American类和British类的对象,编译器不能根据代码直接确定调用那个类中的speak()方法,知道运行时才能根据产生的随机数n的值来确定human[i]到底代表哪一个子类的对象,这样才能最终确定调用的是那个类的speak()方法,这就是动态绑定.

上一篇 下一篇

猜你喜欢

热点阅读