SCJP認證 第二章2.2繼承、IS-A、HAS (2.1.0 繼承)

目標:

5.5 編寫代碼,實現IS-A關係和/或HAS-A關係。

繼承在Java中無處不在。可以斷言,不使用繼承,及時編譯最微小的Java程序也幾乎(幾乎?) 是不可能的。爲了探討這一主題,我們將使用instanceof運算符。對於這個運算符,現在只需記住:如果被測試的引用變量是比較的類型,那麼instanceof將返回true。以下代碼:

將產生如下輸出:

they're not equal

t1's an Object

 其中的equals()方法來自何處?引用變量t1是Test類型,而Test類中沒喲uequals()方法。第二if測試詢問t1使用爲Object類的一個實例,由於確實如此(稍後將詳細介紹),因此ig測試會成功。

 繼續我們的話題。t1如何能夠稱爲Object類型的一個實例,我們只是說它是說它是Test類型的嗎?我們確信這裏,你已經走在我們的前面,但它證明Java中的每個類都是Object類的子類(當然,Object類本身除外) 。換句話說,你曾經使用或編寫過的每個類都繼承自Object類。你可以使用用equals()方法、clone()方法,以及notify()、wait()等其他方法。無論何時創建一個都會自動繼承Object類的所有方法。

爲什麼呢?比如考慮equals()方法。java的創建者正確地假定Java程序員非常普遍希望比較他們累的實例,以檢驗相等性。如果Object類沒有equals()方法,則你以及所有的其他Java程序員都將不得不機子編寫這樣一個方法。一個equals()方法被繼承了數十億次。

對於考試,你只需要知道可以通過擴展類在Java中創建繼承關係。理解繼承的使用還有兩個重要的理由:

  • 促進代碼服用。
  • 使用多態性。 

讓我們從服用開始。一種常見的設計方法是:創建類的相當一般化的一個版本,其目標是創建繼承它的更爲特殊化的子類。例如:

 

輸出如下:

 displaying shape

moving game piece

 

繼承的第二種(以及相關的) 用法是允許以多態方式訪問你的類,多態性也是由接口提供的一種能力,但是將在稍後再介紹它。假定你有一個GameLauncher類,它想虛幻遍歷一列不同類型的GameShape對象,並且在每個對象上調用display()方法。當你編寫這個類時,你並不知道其他任何人將編寫的每種可能的GameShape子類,但你確信自己不希望重新編寫代碼,僅僅是由於有人決定在6個月後腰構建一個Dice形狀。

關於多態性(“許多形式”) 的美妙之處是:可以將GameShape的任何子類視作GameShape。換句話說,可以在你的GameLauncher類中編寫代碼,指出:”只要是繼承自(擴展)“GameShape,那麼並不在意對象的類型是什麼。

攝像有兩個特殊子類PlayerPiece和TilePiece,它們擴展了更加泛型的GameShape類:

現在設想測試類具有一個方法,它帶有聲明的GameShape變元類型,這意味着它可以獲取任何類型的GameShape。換句話說,GameShape的任何子類都可以傳遞給具有GameShape類型的變元的方法。以下代碼:

輸出如下:

displaying shape

displaying shape

 

關鍵點在於,doShape()方法是用GameShape變元聲明的,但可以向它傳遞GameShape的任何子類型(這裏就是一個子類) 。然後,該方法可以調用GameShape的任何方法,而無需考慮傳遞給方法的對象實際運行時的類類型,儘管有這方面的暗示。doShapes()方法只知道對象是GameShape類型,因爲這是參數的聲明方式。使用聲明爲GameShape類型的引用變量——而不考慮該變量是方法參數、局部變量——意味着只能對它調用GameShape的方法。

能夠在引用上調用的方法完全依賴於變量的聲明類型,而不管該引用的實際對象是什麼。這意味着本鞥使用GameShape變量調用(比如說) getAdjacent()方法,即使傳入的對象是TilePiece類型也是如此(當探討接口時,將再次看到一點)。

 

IS-A關係和HAS-A關係

 對於考試,要能夠看懂代碼,並判斷是IS-A還是HAS-A關係。規則很簡單,因此,這應該是幾個幾乎不需要動腦筋就能夠正確回答的問題之一。

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章