1. 程式人生 > 其它 >面向物件(繼承)-->2

面向物件(繼承)-->2

 

 

定義一個父類:

 

定義一個學生類(Student)繼承該類(Role):

 

 測試類:

 繼承的記憶體圖原理及實現機制:

問題一:子類是否可以繼承父類的構造器?

不能,因為類是自帶構造器的,構造器的作用是生產物件,父類的構造器用於生產父類物件,子類構造器用於生產子類物件,兩者互不干擾,沒有半毛錢關係。

問題二:子類是否可以繼承父類的私有成員?

這是一個有爭議的知識點,個人看法:可以,但是不能直接訪問。如下圖所示的繼承關係,比如我們雖然通過private修飾了父類的成員變數和成員方法,但我們可以對外提供public修飾的方法。這點類似於封裝的思想。

問題三:子類是否可以繼承父類的靜態成員?

這也是一個有爭議的知識點,個人看法:不可以,靜態成員隸屬於類,在程式執行時只會被載入一次,也就是說它只有一份,屬於某一個類本身。但又因為靜態成員是被共享訪問的,所以子類可以訪問父類的靜態成員。

綜上所述,能繼承 != 能訪問,能訪問 != 繼承。

 Java只支援單繼承,不支援多繼承的原因(二義性問題):

繼承後成員變數,成員方法的訪問特點:

 

 執行結果:

 

不難看出:在子類方法中訪問成員變數和成員方法時,滿足就近原則。查詢過程:子類區域性 --> 子類成員 --> 父類成員 (父類成員也沒有則報錯)!如果出現了重名的方法,會優先使用子類的,如果一定要在子類中訪問父類成員,就需要藉助 super 關鍵字(使用範圍與 this 相同,即只能在方法中使用),格式:super.父類成員變數/方法

。並且,當子類名與父類名同名時,使用子類的方法(則該方法稱之為方法重寫)。

方法重寫:

 繼承後構造器的特點:

子類中所有的構造器都會先訪問父類中無參的構造器,在執行自己,原因就是子類構造器的第一行會預設帶上一行程式碼:super(),他會先呼叫父類的無引數構造器

 

 

 

 

 

 至此,我們也可以解開這樣的疑惑:在學習面向物件構造器的時候,為什麼一個實體類有引數構造器可有可無,但無引數構造器就必須要有呢?,並且一旦提供了有引數構造器,就必須提供無引數構造器。

因為在正常情況下,一個類如果被其他類繼承了,那麼它就會成為一個父類,子類構造器裡邊會自動呼叫父類的無引數構造器[子類第一行的程式碼預設為:super()],如果父類不提供無引數構造器,則程式報錯!

 

 

關鍵字 訪問成員變數   訪問成員方法 訪問構造方法
this this.成員變數 this.成員方法 this(...)
訪問本類成員變數 訪問本類成員方法 訪問本類構造器
super super.成員變數 super.成員方法 super(...)
訪問父類成員變數 訪問父類成員方法 訪問父類構造器

 補充:this訪問本類構造器(兄弟構造器)

案例:在學生資訊管理系統中,如果一個學生提供了姓名和國家,則使用該生提供的資訊,如果沒有提供則預設國家為中國。

 

 

 

 

 

 那麼問題來了,我們之前說過子類的構造器會在第一行使用super()自動呼叫父類的無引數構造器,圖下的程式碼還會呼叫父類的無引數構造器嗎?

答案是否定的,可以看到,當我們手動在該構造器裡邊的第一行加上super()時,程式報錯了,原因是什麼呢?

原因就是子類this會呼叫本類的其他構造器,而其他構造器會通過super()呼叫父類的構造器,也就是說,本類的其他構造器最終還是會呼叫父類的無引數構造器。

所以:this和super只能出現在構造器的第一行,二者不可放在同一個構造器中!