繼承與組合 java
繼承是實現類重用的重要手段,但繼承帶來一個最大的壞處:破壞封裝。組合也是實現類重用的重要方式,而採用組合方式來實現類重用則能提供更好的封裝性。工具
使用繼承的注意點設計
子類擴展父類時,子類能夠從父類繼承獲得Field和方法,若是訪問權限容許,子類能夠直接訪問父類的Field和方法,至關於子類能夠直接複用父類的Field和方法。指針
封裝:每一個類都應該封裝它內部信息和實現細節,而只暴露必要的方法給其餘類使用。code
爲了保證父類的封裝性,設計父類應該遵循以下規則:對象
》儘可能隱藏父類的內部數據,儘可能把父類的全部Field都設置成private訪問類型,不要讓子類直接訪問父類的Field。繼承
.》不要讓子類能夠隨意訪問,修改父類的方法。父類中那些僅爲輔助其餘的工具方法,應該使用private修飾;若是父類中的方法須要被外部類調用,則必須以public修飾,但又不但願子類重寫該方法,使用final修飾;若是但願父類的某個方法被子類重寫,但不但願其餘類自由訪問,則使用protected修飾。字符串
》儘可能不要在父類構造器中來調用將要被子類重寫的方法。class
class Base { public Base() { test(); } public void test() { System.out.println("將被子類重寫的方法"); } } public class Sub extends Base { private String name; public void test() { System.out.println("子類重寫父類的方法,"+"其name字符串的長度"+name.length()); } public static void main(String[]args) { //下面代碼會引起空指針異常 Sub s= new Sub(); } }
當系統識圖建立Sub對象時,一樣會先執行其父類構造器若是父類構造器調用了被其子類重寫的方法,則變成調用被子類重寫後的方法。當建立Sub對象時,會先執行Base類中的Base構造器,而Base構造器中調用了test方法——並非調用父類的test方法,而是調用的i之類的test方法,此時Sub對象的nameField是null,所以空指針異常。test
若是想把某些類設置成最終類,即不能被當成父類,則可使用final修飾;使用private修飾這個類的全部構造器,從而保證子類沒法調用該類的構造器,也就沒法繼承該類。使用private修飾的父類,能夠另外提供一個靜態方法,用於建立該類的實例。
什麼狀況下須要從父類派生新的子類呢?
》子類須要額外增長屬性,而不單單是屬性值的改變。
》子類須要增長本身獨有的行爲方式(包括增長新的方法或重寫父類的方法)。
利用組合實現複用
若是須要複用一個類,出了繼承外,還能夠把該類當成另外一個類的組合成分,從而容許新類直接複用該類的public方法。組合是把舊類對象做爲新類的Field嵌入,用以實現新類的功能,用戶看到的是新類的方法,而不能看到被起嵌入對象的方法。
什麼時候使用繼承?組合?
將一個較爲抽象的類改變成能使用與某些特定需求的類使用繼承。若是兩個類之間有明確的總體,部分的關係,使用組合。