1. 程式人生 > >Java程式設計思想 第八章讀書筆記-多型

Java程式設計思想 第八章讀書筆記-多型

多型是面向物件三種基本特徵之一(繼承,抽象,多型)

多型存在的意義是什麼?自己的理解,多型消除了型別的耦合。如果一個方法的引數是基類物件,如果沒有多型,那麼我們需要判斷傳入的引數到底是基類的哪個衍生類,然後還掉統一方法名的方法,程式碼比較冗餘,和類的耦合度很高。有了多型,我們可以根據動態繫結,在執行時動態的找到引數對應的類,實現對應的方法,效果是我們不需要程式碼裡去判斷它是什麼型別,我們知道的是他們擁有相同的介面,我們只需要呼叫介面方法就可以了。多型的使用,讓介面方法和具體實現進行分離,我的理解是解除了介面方法與具體實現的耦合。這個的效果就是,呼叫不用類的同一個方法名方法,每個類的實現效果不一樣。

要和封裝的概念進行區分,封裝是封裝了具體實現(通過private方法)把介面和實現分離。

1.向上轉型 當一個方法的引數是一個基類,那麼這個引數也能接受這個類的匯出類,而且我們不需要做任何型別轉換,因為匯出類必定存在基類的介面。

2.動態繫結和工廠設計方法 

什麼是繫結?將方法的呼叫同方法的主體關聯起來。動態繫結是什麼?編譯器是不知道物件的型別的,但是卻能呼叫正確的方法體然後進行呼叫。(實現原理:在物件中有有關於型別資訊的引數)。Java中除了final 和 static方法外,其他方法都是動態繫結,這就意味著我們不需要自己進行判斷它是否是動態綁定了。final修飾的方法我們知道,是不允許繼承和重寫的,更加重要的一點是final修飾的方法關閉了動態繫結,編譯器可以為final方法呼叫生成更加有效的程式碼。

工廠思想,我們已經知道了,動態繫結,在執行時找到正確的方法體去實現方法。所以我們可以創造一個方法用來返回基類物件例項,而建立的可以是基類,也可以是衍生類。在方法裡,我們根據不同的情況new 出來不同的衍生類物件,然後通過return 向上轉型成基類。

再論擴充套件性,通過動態繫結和工廠思想,我們明白了一個問題,方法呼叫只會呼叫基類的介面。我們在新增更多的衍生類的時候,不需要增加更多的識別型別的程式碼就可以實現介面功能的擴充套件,我們只需要在工廠方法裡新增一個新的情況,new 出來我們新增的類,不需要修改別的程式碼,就能實現擴充套件。

方法是多型的,那麼變數是否也是多型的?成員變數也是多型的,為了避免誤會,我們儘量在衍生類裡面使用和父類不同的成員變數名,或者我們儘可能的把基類的成員變數設定為private。 

什麼樣的沒有多型性,靜態的(static) final的

3.既然方法有多型,構造方法也是特殊的方法,是否具有多型?no  構造方法不具有多型性(這不就亂了嘛)。但是我們需要了解構造器如何通過多型在複雜層次結構中的運作。

構造器的呼叫順序 逐層向上使得每個基類的構造器都能夠得到呼叫。這樣做的意義是防止呼叫某個方法這個方法需要使用的成員變數沒有初始化,否則不肯能構造出完整的物件。

物件的清理順序和構造順序完全相反,我們基本上做法是重寫基類的清理方法,在清理方法中清理當前類的物件需要清理的資料,然後呼叫父類的清理方法(不呼叫就不清理基類物件)。為什麼要後呼叫基類的清理方法,我們的處理方式要根據依賴關係來,衍生類依賴基類,因此這樣清理方式是安全的。

如果在一個構造器內部呼叫正在構造的物件的某個動態繫結方法會發生什麼情況呢。在一般方法內部,動態繫結的呼叫是在執行時決定的,因為物件無法知道它是屬於方法所在的那個類,還是那個類的匯出類。

初始化的實際過程:1.在其他任何事物發生之前,將分配給物件的空間初始化為二進位制0;2.呼叫基類的構造器,如果構造器裡面有方法在衍生類被複寫,呼叫複寫的方法3.然後按照衍生類宣告的順序呼叫成員的初始化方法4.呼叫匯出類構造器

4.協變返回型別,在基類中,我們有一個介面方法返回值是基類物件,我們可以在這個類的衍生類中,覆寫該方法,並且返回值為這個返回值類的其中一個衍生類。

5.用繼承進行設計   繼承和組合都是程式碼複用比較好的實現方式,我們決定使用哪個實現方式是根據自己場景需求的,組合方式的好處是,我們可以在執行時決定使用具體型別,而繼承不能多繼承多個類。如果我們不需要向上轉型的時候我們可以考慮是否需要繼承。

向上轉型和向下轉型 向上轉型-需要理解一點就是衍生類介面只會等於基類介面數,我們的擴充套件將無法提供服務。向上轉型是安全的。  向下轉型-需要進行檢查,如果不檢查有可能會造成型別轉換異常。