多態性:
是對對象來說的。extends或implements是多態性的前提。
經理類繼承僱員類。小明是一個經理對象,這個對象既有經理形態,也有僱員形態。一個對象有多種形態,這就是對象的多態性。
多態性格式:父類引用指向子類對象
格式:父類名稱 對象名 = new 子類名稱();
或:接口名稱 對象名 = new 實現類名稱();
可以這樣理解:子類被當做父類來看待(一個經理被當做僱員來看待,一直貓被當做動物來看待)。而對象只能引用父類特有的方法。
多態訪問成員變量的兩種方式:
-
直接通過對象名稱訪問成員變量:看等號左邊是誰,優先用誰,沒有則向上找。(編譯看左邊,運行還看左邊)
Fu obj = new Zi(); System.out.println(obj.num);
- 間接通過成員方法訪問成員變量:看該方法屬於誰優先用誰,沒有則向上找。(先看右邊子類中有沒有該方法,沒有則向上找)
多態訪問成員方法:
訪問成員方法的規則:看new的是誰,則優先用誰,沒有則向上找(編譯看左邊,運行看右邊)。
先看左邊父類中有沒有該方法,沒有則編譯不通過報錯,但運行時是看右邊子類方法,沒有則向上找。只用於成員方法,不適用於成員變量。
向上轉型和向下轉型
在Java中,對象變量是多態的。
Employee e;
e = new Employee(...);
e = new Manager(...);//Manager繼承Employee
這裏的Employee類變量可以引用Employee類對象和任何一個Employee類的子類。
在《JAVA核心技術卷一》P152的代碼中
Manager boss = new Manager(...);
Employee[] staff = new Employee[3];
staff[0] = boss;
Employee boss = new Employee(...);
Manager[] staff = new Manager[3];
staff[0] = boss;//錯誤!
boss是Manager類對象,staff數組是Employee類對象,所以staff可以和boss指向同一對象,且編譯器將staff[0]看成Employee對象。如果是下面這段代碼會報錯,因爲不是所有的僱員都是經理(類比double轉換int可能會損失精度)。
向上轉型一定是安全的,從小範圍轉向了大範圍(從小範圍的經理轉向大範圍的僱員,從小範圍的貓轉向大範圍的動物,類似於從小範圍的int轉向大範圍的double不會損失精度)。
對象的向上轉型其實就是多態寫法:
//格式:父類名稱 對象名 = new 子類名稱();
//右邊創建了一個子類對象,把它當做父類看待使用
Employee Manager = new Manager()
//創建了一個經理對象,把它當做僱員來看待
向下轉型是一個【還原】的動作,但要保證對象一開始創建的時候 ,就是經理,才能由僱員向下轉型爲經理。(用instanceof關鍵字判斷前面的對象是不是後面的類型)
String c = (String)staff[1];
//會產生編譯錯誤,因爲String不是Employee的子類
- 只能在繼承層次內進行類型轉換
- 將超類轉換成子類(向下轉型)之前,應該使用instanceof進行檢查
- 類型轉換不是一種好的做法,多態的對象向下轉型是爲了使用子類特有的方法,這種情況下應該檢查超類的設計是否合理,也許重新設計超類並添加相應方法纔是正確做法。儘量少用類型轉換和instanceof