1. 程式人生 > >多型、繼承、this、super、及多型執行方法時的原理

多型、繼承、this、super、及多型執行方法時的原理

先放一下多型的定義:

(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(引數)呼叫其它建構函式,也必須放在第