多態:基於繼承的向上轉型功能,允許同一種類型同一行爲有不同的表現。
多態的優點:多態不但能夠改善代碼的組織結構和可讀性,還能夠創建可擴展的程序—即無論在項目最初創建時還是在需要添加新功能時都可以"生長"的程序。
多態的作用:消除類型之間的耦合關係。
再論向上轉型
當父類的引用指向子類對象時,就發生了向上轉型,即把子類類型對象轉成了父類類型。舉例:水杉是樹的一種(樹的子類),我們可以稱水杉是樹。
轉機
public static void tune(Instrument i) {
i.play(Note.MIDDLE_C);
}
上面代碼中tune()方法接受了一個Instrument引用。在這種情況下,編譯器是怎麼樣知道Instrument引用指向的是A對象,而不是B對象或C對象。要解決這個問題需要了解綁定了。
綁定:將一個方法調用同一個方法主體關聯起來。
前期綁定:程序在執行前進行綁定。
後期綁定:程序運行時根據對象的類型進行綁定,後期綁定也叫做動態綁定或運行時綁定。
Java中默認是動態綁定。特殊:static方法和final(private方法屬於final方法)方法不存在多態性,不是動態綁定。
動態綁定好處:使得多態中的基類對象可以正確執行相應的導出類對象方法。
可擴展性:多態使得擴展新類型和擴展基類不會對已有代碼(調用基類方法的代碼)產生影響。它可以讓程序員“將改變的事物與不變的事物分離開”。
不可以覆蓋private方法。子類是否會覆蓋父類方法,按照子類是否可以訪問到父類該方法來決定是否可以覆蓋。
域與靜態方法:多態特性(動態綁定)只是針對方法的。域和靜態方法不具有這種特性。
構造器和多態
構造器是隱式static方法,所以不具有多態特性。
構造器的調用順序:(其實這個知識點在之前已經有提到了)
用例:
package test;
class Dog {
public Dog() { System.out.print("汪汪"); }
}
class Cat {
public Cat() { System.out.print("喵喵"); }
}
class Mouse {
public Mouse() { System.out.print("滋滋"); }
}
class Animal {
public Animal() {System.out.print("動物"); }
}
class Bird extends Animal {
public Bird() { System.out.print("鳥"); }
}
class Sparrow extends Bird {
public Sparrow() {System.out.print("麻雀");}
}
public class test extends Sparrow {
private Dog dog = new Dog();
private Cat cat = new Cat();
private Mouse mouse = new Mouse();
public test() { System.out.print("吱吱"); }
public static void main(String[] args) {
new test();
}
}
答案:動物鳥麻雀汪汪喵喵滋滋吱吱基類的構造器總是在導出類的構造過程中被調用,而且按照繼承層次逐漸向上鏈接,以使每一個基類的構造器杜能得到調用。
繼承與清理:通過組合和繼承方式創建新類時,通常情況都是不需要擔心對象的清理問題,子對象通常都會留給垃圾回收進行處理。
如果確實需要做清理時,必須非常小心謹慎:在使用完之後按照創建逆序清理,即sub.dispose()然後super.dispose()來清理。
構造器內部的多態方法行爲:
在調用子類構造器的過程中,會先調用父類構造器,此時子類構造器還沒調用完成,子類對象也沒有執行初始化,如果在父類構造器裏調用多態方法,那麼這個方法是可以產生多態行爲特徵的,但是由於子類構造器沒有執行完,因此子類的初始化還沒完成,多態方法裏對子類成員變量的獲取只能拿到默認值0,false,null。
總結
多態意味着“不同的形式”。在面向對象的程序設計中,我們持有從基類繼承而來的的相同接口,以及使用該接口的不同形式:不同版本的動態綁定方法。