Thinking In Java Part02(繼承)

1、繼承
	有兩種方法可以使基類與導出類產生差異。
		第一種:直接在導出類中添加新方法。應該仔細考慮基類也需要這些額外方法的可能性。
		第二種:改變先有基類的方法的行爲,這被稱爲覆蓋
1.1、是一個與像是一個關係
	繼承應該只覆蓋基類的方法(而並不添加在基類中沒有的新方法)嗎?如果這麼做,就意味着導出類和基類是完全相同的類型,因爲它們具有完全相同的接口。結果可以用一個導出類對象來完全替代一個基類對象。這可以被視爲純粹替代,通常稱之爲替代原則。在某種意義上,這是一種處理繼承的理想方式。這種情況下的基類與導出類之間的關係稱爲is-a(是一個)關係,因爲可以說“一個圓形就是一個幾何形狀”。判斷是否繼承,就是要確定是否可以用is-a來描述類之間的關係。
	有時必須在導出類型中添加新的接口元素,這樣也就擴展了接口。這個新的類型仍然可以替代基類,但是這種替代並不完美,因爲基類無法訪問新添加的方法。這種情況我們可以描述爲is-like-a(像是一個)關係。新類型具有舊類型的接口,但是它還包含其他方法,所以不能說它們完全相同。例如家裏有控制冷氣設備的接口,你有一個空調來製冷,但是現在空調壞了,你用一個既能製冷又能制熱的熱力泵替換了,那麼這個熱力泵就is-like-a空調,它可以做更多的事。但是房子的控制系統 被設計爲只能控制冷氣設備,所以它只能和新對象中的製冷部分進行通信。儘管新對象的接口已經被擴展,但是現有系統除了原來接口之外,對其他東西一無所知。
	最後我們會發現製冷系統這個基類不夠一般化,應該將其更名爲“溫度控制系統”,讓它可以包括制熱功能,這樣我們可以套用替代原則了。
2、伴隨多態的可互換對象
	在處理類型的層次結構時,經常想把一個對象不把它當作它所屬的特定類型來對待,而是將其當作其基類的對象來對待。這使得人們可以編寫出不依賴於特定類型的代碼。在“幾何形”的例子中,方法操作的都是泛型(generic)的星座,而不關係它們是圓形、正方形、三角形還是其他什麼尚未定義的形狀。所有的幾何形狀都可以被繪製、擦除和移動,所以這些方法都是直接多對一個幾何形對象發送消息,它們不用擔心對象將如何處理消息。
	通過導出新的子類型而輕鬆擴展設計的能力是對改動進行封裝的基本方式之一,能極大地改善我們的設計,同時降低軟件維護的代價。
	但是使用泛化的對象,編譯器不知道應該執行哪一段代碼。問題的答案,也是面向對象程序設計的最重要的妙訣:編譯器不可能產生傳統意義上的函數調用。一個非面向對象編程的編譯器產生的函數調用會引起所謂的前期綁定。前期綁定:意味着編譯器將產生對一個具體函數名字的調用,而運行時將這個調用解析到將要被執行的代碼的絕對地址。然而在OOP中,程序直到運行時才能夠確定代碼的地址,所以當消息發到一個泛化對象時,必須採用其他的基址。
	爲了解決確定代碼位置的問題,面向對象程序設計語言使用了後期綁定的概念。當向對象發送消息時,被調用的代碼直到運行時才能確定。編譯器確保被調用方法的存在,並對調用參數和返回值執行類型檢查(無法提供此類保證的語言被稱爲是弱類型的),但是並不直到將被執行的確切代碼。
	爲了執行後期綁定,Java使用一小段特殊的代碼來替代絕對地址調用。這段代碼使用在對象中存儲的信息來計算方法體的的地址。這樣,根據這一小段代碼的內容,每一個對象都可以具有不同的行爲表現。當向一個對象發送消息時,該對象就能夠直到對這條消息應該做什麼。
	在某些語言中,必須明確地聲明希望某個方法具備後期綁定屬性鎖帶來的靈活性(C++是使用virtual關鍵字來實現的)。在這些語言中,方法在默認情況下不是動態綁定的。而在java中,動態綁定是默認行爲,不需要添加額外的關鍵字來實現多態。
	將導出類看作是它的積累的過程被稱爲向上轉型(upcasting)。轉型(cast)這個名稱的靈感來自於模型鑄造的塑模動作;而向上(up)這個詞來源於繼承圖的典型佈局方式:通常基類在頂部,而導出類在其下部散開。因此,轉型爲一個記錄就是在繼承圖中向上移動。
	在Java編譯器在編譯方法的時候,並不能知道這個方法要處理的確切類型。通常會期望它的編譯結果是調用基類的方法,而不是具體的導出類的方法。正是因爲多態才使得事情總是能夠被正確處理。
3、單根繼承結構
	是否所有的類最終都繼承自單一基類。在Java(還包括除C++外所有的OOP語言),答案是yes,這個終極基類的名字就是Object。
	在單根繼承結構中的所有對象都具有一個共用接口,所以它們歸根到底都是相同的基本類型。
4、容器
	通常來說,你不知道在解決某個特定問題時需要多少個對象,或者它們將存活多久, 那麼就不可能知道如何存儲這些對象。如何才能知道需要多少空間來創建這些對象呢?因爲這類信息僅在運行時才能獲得,所以不能知道。
	對於面向對象設計的大多數問題,這個解決方案可以爲:創建另一種對象類型。這種新的對象類型持有對其他對象的引用。當然, 你可以用在大多數語言中都有的數組類型來實現相同的功能。這個通常被稱爲容器(也稱爲集合)。
	List用於存儲序列,Map也被稱爲關聯數組中,用來建立對象之間的關聯,Set每種對象類型只持有一個。
	ArrayList隨機訪問元素是一個花費固定事件的操作,但是,對LinkedList來說,隨機選取元素需要在列表中移動,這種代價是高昂的,訪問越靠近表尾的元素,花費的時間越長。如果想在序列之間插入一個元素,LinkedList的開銷比ArrayList小。
5、參數化類型
	爲了在向下轉型的時候,排除運行時錯誤,所以創建容器讓它知道自己所保存的對象的類型,從而不需要向下轉型以及消除犯錯誤的可能。這種解決方案被稱爲參數化類型基址。參數化類型就是一個編譯器可以自動定製作用於特定類型上的類。
	Java SE5的重大變化之一就是增加了參數化類型,在Java中它稱爲 泛型。
6、對象的創建和生命期
	對象的數據位於何處?怎樣控制對象的生命週期?爲了追求最大的執行速度,對象的存儲空間和生命週期可以在編寫程序時確定。
		6.1、通過將對象置於堆棧(它們有時被稱爲自動變量或限域變量)或靜態存儲區域內來實現。這種方式將存儲空間分配和施放置於優先考慮的位置,某些情況下這樣的控制非常有價值。但是也犧牲了靈活性,因爲必須在編寫程序時知道對象的確切數量、生命週期和類型。	
		6.2、在被稱爲堆(heap)的內存池中動態地創建對象,這種方式,直到運行時才知道需要多少對象,以及它們的生命週期和具體類型。因如果需要一個新對象,可以在需要的時空直接在堆中創建。因爲存儲空間是在運行時被動態管理的,所以需要大量的時間在堆中分配存儲空間,可能遠遠大於在毒地站中創建存儲空間的事件。
	Java採用了動態內存分配方式。每當需要新對象時,用new關鍵字來構建此對象的動態實例。
	Java的垃圾回收器因爲所有都系 都是繼承自單根基類Object且只能以一種方式創建對象(在堆上創建)這兩種特性。所以可以用來處理內存施放問題,知道對象什麼時候不再被使用。          
7、Web是什麼
	客戶/服務器系統的核心思想:系統具有一箇中央信息存儲池,用來存儲某種數據,它通常存在於數據庫中,你可以根據需要將它分發給某些人員或或機器集羣。客戶/服務器概念的關鍵在於信息存儲池的位置集中於中央,這使得它可以被修改,並且這些修改啊將被傳播給信息消費者。總之,信息存儲池、用於分發信息的軟件以及信息與軟件所駐留的機器或集羣被稱爲服務器。駐留在用戶機器上的軟件與服務器進行同學,以獲取信息、處理信息,然後將它們顯示在被稱爲客戶機的用戶機器上。                                  
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章