多態、繼承、this、super、及多態執行方法時的原理
- 2019 年 10 月 3 日
- 筆記
先放一下多態的定義:
(360詞典上的哈)
多態(Polymorphism)按字面的意思就是”多種狀態”。在面向對象語言中,介面的多種不同的實現方式即為多態。引用Charlie Calverts對多態的描述–多態性是允許你將父對象設置成為一個或更多的他的子對象相等的技術,賦值之後,父對象就可以根據當前賦值給它的子對象的特性以不同的方式運作(摘自”Delphi4 編程技術內幕”)。簡單的說,就是一句話:允許將子類類型的指針賦值給父類類型的指針
看完上面的定義,可能你會覺得有點懵,其實也就是兩句話:
1.一種事物的多種形態
2.父類引用指向子類對象
首先來解釋第一點:
多態是指的一種事務的多種形態。
說明一下抽象:
抽象:忽略物體的實際屬性的狀態、個體的特殊行為等,忽略問題的表現,而關注問題的本質的一個過程。
比如說,我們每一個人都是一個個體。我們就可以把個體的特殊行為和特殊屬性值忽略,而抽取每一個人的共性作為人這個類。
而我們實現對象的時候再把我們個體的這些特殊屬性值為人這個類的屬性賦值。而在類中,我們人這個類雖然有屬性,卻沒有具體指。
為類的屬性填值和改變具體行為的過程,被稱為類的實現也就是建立一個對象。
簡化為一句話哈(抽象是忽略個體實際而轉化為一個類型的過程。實例化是將類型特殊化為一個個體的過程)
然後下一個概念是繼承:(一定要理解昂)
繼承是將一個類型泛化為多個類型的過程,且子類型擁有(繼承了)父類型所擁有的所有元素(所有非private類型的方法和變數)
這句話的意思就是,這個類型又可以分為多個子類型,舉個例子的話,人這個類型可以泛化為男人和女人這兩個具體一點的類型。
首先說明一下上面的的繼承所得到的東西:
我們之前的博文有講到過類的載入機制,在static那一篇。
在一個對象的創建過程中的第二個階段,指向非靜態程式碼塊和構造函數的時候我們也執行的父類的非靜態程式碼塊和構造函數函數,
這個過程是不是就表明,在創建一個類的時候,我們一定也會創建一個它所對應的父類(對於每個對象來說都是如此,所以其實Java創建一個對象,其實創建了好多個,顯得特別臃腫)
而在我們每一個對象中都有一個super、this引用,super指向它的直接父類、this指向自己。(接下來會講到)
類繼承的時候會繼承父類對象的的所有的非private修飾的成員變數和成員方法。
對於變數來說它實際上是把父類對象的可以繼承的成員變數賦值了一份放在了自己這裡。
但是對於成員變數來說則是各自有各自的區域,存儲的是不同的成員變數,不過子類會拷貝一份父類的非private的成員變數。
對於方法來說,則不會繼承父類的private成員方法,其它的方法子類繼承了。但是如果自己寫了一個除了方法體和父類的某個方法重名的方法(返回值類型可以不同,不過返回值類型必須是父類返回值類型的子類(多態)),則會覆蓋父類的那個方法。
對於方法重寫有兩個注意事項:
子類的方法不能比父類的方法的訪問許可權小,拋出的異常不能比父類的大。(接下來講)
接下來就該多態了:
我們說多態是一種事務的多種形態,其實就是說的我們的泛化,不過比泛化更具體一下,多態是,把泛化實例化了。就是把泛化的類型實例化了。
第二局是父類引用指向子類對象,則是多態的表現形式。它的意思是說,我們可以使用父類類型的引用指向子類類型的對象。(好好體會一下就懂了)
這就是多態了。用一種大類型來指向多種小類型,來描述事物類型之間的一種集合關係(同屬於一種集合,但是又不是同一種類型,比如哺乳動物、人、狗狗)人和狗是哺乳動物的多種形態
接下來我們該說一下使用多態時應該注意的點。其實理解了上面的下面的就自己能想到了。
A 是父類 A1、A2是子類
A a = new A1()
使用多態時,調用(a.value)屬性的時候,實際上是調用的a的父類型的屬性,也就是A類型的,因為,人家會判斷你的引用類型。
而使用a.str()方法時,則是使用的子類的方法,因為,在調用方法時,它不會去檢查引用類型。直接調用的就是子類所擁有的方法。
對於靜態方法和靜態變數來說,則會檢查引用類型。調用對應引用類型的類的靜態變數和函數。(上面這三句話,一定要記住昂,除了方法之外,其它的都會檢查引用類型)
討論完繼承、多態之後,我們還需要討論一下this、super關鍵字。這個是在每個對象中都有的。
this是指向當前對象的一個引用,super是指向其父類對象的一個引用。
this()執行當前類的無參構造函數
super()執行父類的無參構造函數,
在類的無參構造函數的第一行默認調用了super()
this()super()不能同時出現,原因自己想一下哦,我們總不可能初始化兩次某個對象吧。
還有關於this、super的一個重要知識點,
this調用的是當前類的方法,super調用的也是它指向的父類的方法。(這裡需要強調一下,雖然父類的方法被子類所覆蓋的,但是這裡指向的是父類的對象,所以是去父類的方法所存儲的地方尋找對應的方法,而不是去this指向的子類的存儲方法的地方尋找。我記得Java中的類的方法只有一份,我記得是這樣啊,不是太確定。不過這個並不影響我們判斷。尋找方法的時候是不判斷引用類型,而是通過引用指向的對象,去這個對象的類型的方法集里找對應的,所以這裡和子類的方法集無關,每一個類有一個方法集)
this 也用來分別成員變數和參數重名的情況
this 、super都不要在靜態環境中使(變數、方法、程式碼塊)用,他們都是在對象生成之後才有的
從本質上講,this是一個指向本對象的指針,super是個關鍵字
super可以用來調用父類中被隱藏的方法和變數
super()必須卸載子類構造函數的第一行
this(參數)調用其它構造函數,也必須放在第一行