面向物件(繼承)-->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只能出現在構造器的第一行,二者不可放在同一個構造器中!