首頁 >Java >java教程 >Java-物件導向-繼承、多型、組合

Java-物件導向-繼承、多型、組合

高洛峰
高洛峰原創
2016-11-17 14:17:081168瀏覽

繼承的特徵

單繼承:每個子類最多只有一個直接父類,注意是直接父類,間接父類個數不限

注意父類的概念:A-->B-->C- ->D,在這裡,ABC都是D的父類,C是D的直接父類,AB是D的間接父類

父類和子類是一般和特殊的關係;子類擴展了父類,子類別是一種特殊的父類別

Object是所有類別的直接或間接父類別;定義一個類別時,若沒有直接指定父類,則預設繼承Object類別

子類別從父類別中繼承了哪些要素

子類別不繼承父類別的建構方法,但總是要呼叫父類別的建構方法

子類別繼承了父類別的實例變數和實例方法、類別變數和類別方法,當然前提是沒有被private修飾

父類別中被private修飾的成員,不會被子類別繼承

父類別中用final修飾的方法,子類別不能重寫

方法的重寫override

子類別和父類別擁有相同的方法簽名,叫做子類重寫了父類的方法

兩同兩小一大原則:

兩同:方法名相同,形參列表相同

兩小:子類方法的回傳值跟父類的相等或更小;子類別方法拋出的異常要跟父類別拋出的相等或更小

一大:子類別方法的存取權限要跟父類別的相等或更大

static:子類別方法要跟父類別方法一致,要嘛是類別方法,要嘛是實例方法,二者不能不一致

方法重寫後,子類別物件將無法存取父類別的方法,但可以在子類別方法中呼叫父類別的方法:super.實例方法,父類別名稱.類別方法

如果父類別方法是private修飾,則子類別不能重寫該方法;如果子類別擁有一個跟父類別private方法相同簽署的方法,這也不是重寫,這是子類別新加入的方法,與父類別的無關

子類別方法可能會和父類別的方法發生重載

父類別中用final修飾的方法,子類別不能重寫

super關鍵字

在子類別中,用super關鍵字呼叫父類別的實例變數或實例方法

super和static不能同時用來修飾方法;就像this不能和static不能同時修飾方法一樣

子類別從父類繼承了一個變量,又再定義了一個變量,而且同名,此時可以用super.變量名或父類名.變量名來訪問父類的這個變量

變量的查找順序

子類方法存取了一個變量,沒有明確指定呼叫者的情況下,按以下順序查找:

當前方法中,是否有同名的局部變量

當前類別中,是否有同名的成員變量

直接父類中,是否有

逐級網上追溯,如果最終沒有找到,那麼提示編譯出錯

super調用父類構造器

子類雖然不會繼承父類的構造器,但總是會調用父類的構造器。呼叫同一個類別的建構器用this,呼叫父類別的用super

明確呼叫:super呼叫語句寫在建構方法的第一行,因為this也要寫在第一行,因此super和this不會同時出現

間接呼叫:子類別方法的第一行寫的是this,被呼叫的建構器還得呼叫父類別的建構器

隱式呼叫:無super無this,系統預設呼叫父類別的無參構造

子類繼承父類,總會一級一級的往上調用父類構造器,直到調用Object的,並且是找到頂部父類構造器後,開始往下一層一層執行

例如下面的程式碼,繼承關係:A-->B-->C-->D

public class Test{  
    public static void main(String[] args) {  
        D d=new D();
    }
} 
class D extends C{    D(){
        System.out.println("D类构造器");
    }
}class C extends B{    C(){
        System.out.println("C类构造器");
    }
}class B extends A{    B(){
        System.out.println("B类构造器");
    }
}class A{    A(){
        System.out.println("A类构造器");
    }
}

輸出:

A類別建構器
B類別建構器
C類別建構器
D類別建構器

如果父類別沒有無參構造,子類別又需要呼叫父類別的無參構造,那麼不能透過編譯

多態Polymorphism

簡單的說,多態就是:在一個金字塔式的繼承體系中,創造底部子類別物件時,用頂端的父類別類型指向這些底部的子類別對象,透過相同類型的引用變數呼叫同一個方法時,會出現不同的結果

多態源自於:繼承+父類型的引用指向子類型的物件+方法的重寫

引用變數有兩個類型,一個是編譯時類型,一個是運行時類型

向上轉型:父類型引用指向子類型對象,向上轉型由系統自動完成

向上轉型的情況下:透過父類型的參考可以呼叫子類別重寫了的方法,但不能存取父類別中沒有子類別中才有的實例變量,也就是說實例變數不具有多態性

instanceof與強制型別轉換

基本型有強制型別轉換,如(double)16;引用型別也存在強制型別轉換

如存在下列繼承鏈:A-->B-->C-->D-->E -->F,B b=new D(),此時用B類型指向D對象,此時可以把b變數轉為ACD類型,但不能轉為EF類型,拋出異常ClassCastException

進行強制類型轉換之前,應先用instanceof進行判斷能不能轉,避免拋出異常

X變數instanceof Y類型:判斷X變數能不能轉為Y類型,可能出現三種情況:

tru​​e表示可以轉,意味著X變數指向的物件的類型,是Y類型或Y的子類型;

false表示不可以轉,意味著X變數的類型與Y類型存在父子繼承關係,不可能是子父關係, X變數指向的物件的類型與Y類型沒有父子或子父關係,二者都是X變數類型的子類型;

編譯不通過,表示X和Y沒有父子或子父繼承關係

繼承與組合

繼承可以實現代碼的複用,但破壞了封裝;組合也可以實現代碼的複用

設計父類遵循的原則:

盡量用private隱藏父類的內部數據,不讓子類直接訪問父類別的成員變數

不要讓子類別隨意存取、修改父類別方法。父類輔助性的工具方法,用private修飾;需要讓外部呼叫的方法,用public;不希望子類重寫的方法用final修飾;希望子類重寫而不希望外部訪問則用protected

不要在父類別構造器中呼叫可能被子類別重寫的方法,後果很嚴重

設計繼承的原則:

子類別需要增加額外的屬性,而不是屬性的改變

子類別需要增加自己獨有的功能或行為,可以增加新方法,或重寫父類別方法

不要光出於程式碼複用的目的設計繼承,而要看實際情況,父類別和子類別是否有"has-a"的關係

不想讓一個類別被繼承:

final:用final修飾該類別為最終類,不能被繼承

private:用private修飾該類別的所有建構方法,這樣子類別就無法呼叫該類別的建構器,就不能繼承了,另外應提供一個靜態方法,用來返回該類別的對象

組合也能實現代碼的複用

A類復用B類的方法

A類中創建B類的對象,並以private修飾

在A類別方法中呼叫B類別物件的方法

組合還是繼承:

繼承:子類別與父類別是"is-a"關係,具體與抽象、特殊與一般的關係

組合:新類別與舊類別是"has-a"關係,整體與局部的關係

其他:

對於子類別從父類別繼承了一個變量,又定義了一個同名變數的情況下,在創建子類別物件時,為這兩個變數都分配了內存,只是父類別變數被隱藏


陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
上一篇:java學習指南下一篇:java學習指南