Java - 繼承(extend)
繼承extend
一 繼承基礎概念
1.在java中使用extends關鍵字來表示繼承關係。當建立一個類時,總是在繼承,如果沒有明確指出要繼承的類,就總是隱式地從根類Object進行繼承。
2.如果兩個類存在繼承關係,則子類會自動繼承父類的方法和變數,在子類中可以呼叫父類的方法和變數。在子類中也可以覆蓋(重寫)父類的方法,屬性也可以覆蓋(這裡用覆蓋不準確,應該是隱藏,下面有講到)。
3.在java中,只允許單繼承,也就是說 一個類最多隻能顯示地繼承於一個父類。但是一個類卻可以被多個類繼承,也就是說一個類可以擁有多個子類。
4.Java介面是支援多繼承的,所以java中的多繼承是通過介面來間接實現的。
5.super關鍵字是直接父類物件的引用,可以通過super來訪問父類中被子類覆蓋的方法或屬性。任何類的構造方法 中,如果建構函式的第一行程式碼沒有顯式的呼叫super(…),那麼java預設都會呼叫super(…)作為父類的初始化函式,所以構造方法中的super()方法加不加都有。
6.繼承關係是傳遞的。
二 繼承中的細節
1.子類繼承父類的成員變數
1)能夠繼承父類的public和protected成員變數;不能夠繼承父類的private成員變數;
2)對於父類的包訪問許可權(default/friendly)成員變數,如果子類和父類在同一個包下,則子類能夠繼承;否則,子類不能夠繼承;
3)對於子類可以繼承的父類成員變數,如果在子類中出現了同名稱的成員變數,則會發生隱藏現象,即子類的成員變數會遮蔽掉父類的同名成員變數。如果要在子類中訪問父類中同名成員變數,需要使用super關鍵字來進行引用。
2.子類繼承父類的方法
1)能夠繼承父類的public和protected成員方法;不能夠繼承父類的private成員方法;
2)對於父類的包訪問許可權(default/friendly)成員方法,如果子類和父類在同一個包下,則子類能夠繼承;否則,子類不能夠繼承;
3)對於子類可以繼承的父類成員方法,如果在子類中出現了同名稱的成員方法,則稱為覆蓋,即子類的成員方法會覆蓋掉父類的同名成員方法。如果要在子類中訪問父類中同名成員方法,需要使用super關鍵字來進行引用。
注意:隱藏和覆蓋是不同的。隱藏是針對成員變數和靜態方法的,而覆蓋是針對普通方法的。(後面會講到)
3.靜態屬性與方法能否被繼承?
靜態變數與靜態方法能被繼承,其實說繼承並不確切,靜態方法與變數是屬於類的方法與變數。而子類也屬於父類,比如說Manage extends Employee,則Manage也是一個Employee,所以子類能夠呼叫屬於父類的靜態變數和方法。注意,子類呼叫的其實就是父類的靜態方法和變數,而不是繼承自父類的靜態方法與變數。但是如果子類中有同名的靜態方法與變數,這時候呼叫的就是子類本身的,因為子類的靜態變數與靜態方法會隱藏父類的靜態方法和變數。(靜態屬性、靜態方法和非靜態的屬性都不能被重寫,只會被隱藏)
4.構造器
子類是不能夠繼承父類的構造器,但是要注意的是,如果父類的構造器都是帶有引數的,則必須在子類的所有構造器中顯示地通過super關鍵字呼叫父類的構造器並配以適當的引數列表。如果父類有無參構造器,則在子類的構造器中用super關鍵字呼叫父類構造器不是必須的。所以一般在程式碼中都會給類新增一個無參的構造器以備用。
下面是個例子說明
class Shape { protected String name; public Shape(){ name = "shape"; } public Shape(String name) { this.name = name; } } class Circle extends Shape { private double radius; public Circle() { radius = 0; } public Circle(double radius) { this.radius = radius; } public Circle(double radius,String name) { this.radius = radius; this.name = name; }
這樣的程式碼是沒有問題的,如果把父類的無參構造器去掉,則下面的程式碼必然會出錯:
改成下面這樣就行了:
5.構造器的呼叫順序:
見另一篇部落格 類的載入機制