知識梳理
1.向上轉(zhuǎn)型的概念:
向上轉(zhuǎn)型又叫自動轉(zhuǎn)型、隱式轉(zhuǎn)型.向上轉(zhuǎn)型就是父類引用指向子類實例,也就是子類的對象可以賦值給父類的對象.
Animal dog = new Dog(); // Dog類是Animal類的子類
注:向上轉(zhuǎn)型是安全的,因為任何子類都繼承并接受了父類的方法.從例子中也可以理解,所有的狗都屬于狗的父類-動物,這是可行的,但是向下轉(zhuǎn)型則不行,若說所有的動物都是狗就不成立.(所以向下轉(zhuǎn)型要通過強制類型轉(zhuǎn)換,后續(xù)章節(jié)中會將解)
?
2.向上轉(zhuǎn)型的應(yīng)用
1)當(dāng)一個子類對象向上轉(zhuǎn)型父類類型以后,就被當(dāng)成了父類對象,所能調(diào)用的方法會減少,只能調(diào)用子類重寫了父類的方法以及父類派生的方法(如set(),get()方法),而不能調(diào)用子類特有的方法.
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(); // 調(diào)用的是子類的方法,輸出結(jié)果是"吃肉"
animal.run();// 訪問子類特有的方法報錯
animal.die();// 調(diào)用的是父類的方法,輸出結(jié)果是"animal死亡"
}
2)父類中的靜態(tài)方法時不允許被子類重寫的
如父類的有靜態(tài)方法die()
當(dāng)子類Dog中也定義同名方法時,此時die()算dog類自己獨有的方法:
Animal animal = new Dog(); // 向上轉(zhuǎn)型
animal.die();// 調(diào)用的是Animal類的die()方法,而不是調(diào)用Dog的die()方法
// 輸出結(jié)果是:animal死亡
知識擴展
??多態(tài)的實現(xiàn)可以通過向上轉(zhuǎn)型和動態(tài)綁定機制來完成,向上轉(zhuǎn)型實現(xiàn)了將子類對象向上轉(zhuǎn)型為父類類型,而動態(tài)綁定機制能識別出對象轉(zhuǎn)型前的類型,從而自動調(diào)用該類的方法,兩者相輔相成.
動態(tài)綁定:
綁定就是講一個方法調(diào)用同一個方法所在的類連接到一起就是綁定.綁定分為靜態(tài)綁定和動態(tài)綁定兩種.
- 靜態(tài)綁定:在程序運行之前進行綁定(由編譯器和鏈接程序完成的),也叫做前期綁定.
- 動態(tài)綁定:在程序運行期間由JVM根據(jù)對象的類型自動判斷應(yīng)該調(diào)用哪個方法,也叫做后期綁定.
靜態(tài)綁定的例子:
??如有一類Human,它派生出來三個子類Chines類,American類和British類,三個子類中都重寫了父類中的方法speak():void,在測試類中用靜態(tài)綁定的方式調(diào)用方法speak().
Chinese c = new Chinese();
c.speak();
American a = new American();
a.speak();
British b = new British();
b.speak();
這種調(diào)用方式是在代碼里指定的,編譯時編譯器就知道c調(diào)用的是Chinese的speak(),a調(diào)用的是American的speak().
動態(tài)綁定的例子:
如果我們在測試類中做以下改動:
// 生成父類對象數(shù)組,數(shù)組長度為5
Human[] human = new Human[5];
int n;
for(int i = 0; i < human.length;i++){
n = (int)(Math.random() * 3); // 隨機產(chǎn)生從0到2中的一個數(shù)
switch(n){
case 0: human[i] = new Chinese();break;
case 1: human[i] = new American();break;
case 2: human[i] = new British();break;
}
}
// 循環(huán)輸出,循環(huán)體中每個對象分別調(diào)用speak()方法
for(int i = 0;i < human.length;i ++){
human[i].speak();
}
此時,Human類中隨機生成Chinese類,American類和British類的對象,編譯器不能根據(jù)代碼直接確定調(diào)用那個類中的speak()方法,知道運行時才能根據(jù)產(chǎn)生的隨機數(shù)n的值來確定human[i]到底代表哪一個子類的對象,這樣才能最終確定調(diào)用的是那個類的speak()方法,這就是動態(tài)綁定.