【Java學習筆記】繼承和多型

weixin_33860553發表於2013-01-04

作者:gnuhpc
出處:http://www.cnblogs.com/gnuhpc/

1.基本語法:
public class Sub extends Base{
}
當Sub和Base在同一個package時,Sub繼承了Base中的public、protected和預設(即未指定訪問級別)訪問級別的成員變數和方法。
當Sub和Base在不同package時,Sub繼承了Base中的public、protected訪問級別的成員變數和方法。
2.Java不支援多重繼承,但可以通過序列的間接繼承進行多重繼承
3.所有Java類都直接或間接的整合了java.lang.object類。Object類定義了Java物件具有的相同行為。
4.過載overload
同一個類中,相同名字的方法,但是引數型別、個數或者順序至少有一項不同。
5.覆蓋override
子類覆蓋了父類的方法,子類方法的名字、引數簽名、返回型別必須與父類相同。若想怪邊返回型別等,但是還想用同一個名字,則可以使用先覆蓋再過載的策略:
public class Base{
    public void method(){
    }
}
public class Sub extends Base{
    public void method(){//覆蓋Base類的method方法
    }
    public int method(int a){//過載Sub類的method方法
    }
}
注意:
a.子類方法不能縮小父類方法的訪問許可權(可以擴大),而且子類不能丟擲比父類方法更多的異常,其必須丟擲和父類方法丟擲的相同的異常,或者子類方法丟擲的異常類是父類方法丟擲的異常類的子類。
b.父類的靜態方法不能被子類覆蓋為非靜態方法。同樣,父類的非靜態方法不能被子類覆蓋為靜態方法。
c.子類可以定義與父類的靜態方法同名的靜態方法,以便在父類中隱藏父類的靜態方法。子類覆蓋靜態方法和覆蓋一般方法的區別是,執行時,JVM把靜態方法和所屬類繫結,而將一般方法和所屬例項繫結。
d.父類的私有方法不能被子類覆蓋。雖然不會出現編譯錯誤,但是實際上子類並沒有從父類繼承這個方法,所以,其並沒有覆蓋關係。
e.父類的抽象方法通過子類實現父類的抽象方法或者子類重新宣告父類的抽象方法來實現覆蓋。
f.父類的非抽象方法可以被覆蓋為抽象方法。
6.super關鍵字
super和this的功能都是使被遮蔽的方法或變數變為可見。不能在靜態方法或者靜態程式碼塊內不能使用super關鍵字。
7.多型
實質:指當系統A訪問系統B的服務時,系統B可以通過多種實現方式來提供服務,而這一切對系統A是透明的。例如:
public class Feeder{
    public void feed(Animal animal,Food food){
        animal.eat(food);
    }
}
Feeder feeder=new Feeder();
Animal animal=new Dog();
Food food = new Bone();
feeder.feed(animal,food);//喂狗骨頭吃
animal=new Cat();
food = new Fish();
feeder.feed(animal,food);//喂貓魚吃
注意animal被定義為Animal型別,但是有可能引用Dog或Cat型別,在呼叫animal.eat的時候,JVM會執行animal變數所引用的例項的eat方法。
需要注意的是:
1)靜態繫結:對於一個引用型別的變數,Java編譯器按照它宣告的型別來處理。例如,Base who = new Sub();
這個who是Base型別的引用變數,Java編譯器就會按照Base型別來處理。要訪問Sub類的成員,則使用強制型別轉換:((sub)who).subVar="123";
這適用於成員變數(包括靜態變數和例項變數),靜態方法
2)動態繫結:對於一個引用型別的變數,執行時JVM按照其實際引用的物件的方法進行繫結。例項方法就屬於這一類。
3)Java允許在具有直接或間接的繼承關係的類之間進行型別轉換,對於向上轉型,不必使用強制型別轉換。
繼承的利弊:
提高程式碼可重用性,是提高系統擴充套件性的有效手段。但是繼承樹若是異常複雜,或被隨意擴充套件,反而會削弱系統的可擴充套件性和可維護性。繼承的最大弱點是打破了封裝,削弱了子類的獨立性。
繼承的原則:
1)不考慮Object,繼承樹應該儘量保持在兩到三層。
2)當一個系統使用一棵繼承樹上的類時,應該儘可能地把引用變數宣告為繼承樹的上層型別。
3)若繼承樹上有介面型別,那麼應該儘可能地把引用變數宣告為繼承樹上層的介面型別。
4)上層完成那些適用於所有子類或大多數子類的方法,否則則設定為抽象方法。
5)在設計繼承類的時候,儘可能的封裝父類的實現細節,也就是把代表實現細節的屬性和方法定義為private型別,若某些實現細節必須被子類訪問則設為protected型別。
6)將不允許子類覆蓋的方法定義為final型別。
7)父類的構造方法中不要呼叫可以被子類覆蓋的方法。
8)某些類不是為了繼承而設計的,那麼採用將類宣告為final型別,或者將這個類的所有構造方法宣告為private型別,然後通過一些靜態方法來負責構造自身的例項的兩種方法禁止繼承。
9)對於一棵設計合理的繼承樹,子類之間會具有不同的屬性和行為。
10)組合關係指的是:類A中包含有類C的屬性,則類A稱為包裝類(整體類),而類C稱作被包裝類(區域性類)。在開發中,組合關係雖然不比繼承關係減少程式碼量,但是維護起來,有更好的鬆耦合性。不使用繼承,而是在類中加入要繼承的類的一個例項成員就是組合。繼承關係是靜態的,在執行時,子類無法改變它的弗雷,但組合關係在執行時可以根據需要改變實現方式。在繼承關係中,子類只能繼承父類的介面,不能取消父類的方法,但是除非覆蓋該方法,並直接丟擲java.lang.UnsupportedOperationExcepetion。而組合則不會自動去繼承父類的方法。

 

作者:gnuhpc
出處:http://www.cnblogs.com/gnuhpc/

相關文章