JAVA類繼承過程中其成員的一些問題
???
一、構造函數(shù)的問題:
???構造函數(shù)不能繼承。子類的構造函數(shù)可以通過super關鍵字顯式調用父類中的構造函數(shù)。如果子類中的構造函數(shù)沒有顯式調用父類中的構造函數(shù),編譯器就會自動在子類的構造函數(shù)中調用父類中參數(shù)為空的構造函數(shù)。于是,當父類中沒有參數(shù)為空的構造函數(shù),而子類中又沒有顯示調用父類的其他構造函數(shù),編譯時就會報錯。這一點需要特別注意。當父類中沒有定義任何構造函數(shù)時,編譯器就會為它指定一個參數(shù)為空的默認的構造函數(shù);如果父類中定義了構造函數(shù),那么編譯器就不會為它指定一個參數(shù)為空的默認構造函數(shù)了。因此,如果某個類有可能成為其他類的父類,為了避免發(fā)生不必要的編譯錯誤,最好為它編寫一個參數(shù)為空的構造函數(shù)。
eg1.父類Sup中沒有定義構造函數(shù),編譯程序將為它指定一個參數(shù)為空的默認構造函數(shù)。子類Sub中也沒有定義構造函數(shù),編譯程序也會為它指定一個參數(shù)為空的默認的構造函數(shù),并且會在這個默認的構造函數(shù)中調用父類的參數(shù)為空的構造函數(shù)。















eg2.父類Sup中沒有定義構造函數(shù),編譯程序將為它指定一個參數(shù)為空的默認構造函數(shù)。子類定義了一個帶整型參數(shù)的構造函數(shù),在這個構造函數(shù)中子類沒有顯式調用父類的構造函數(shù),所以編譯器為在它里面調用父類中參數(shù)為空的構造函數(shù)。





















eg3.父類中定義了一個帶整型參數(shù)的構造函數(shù),因此編譯器不再為它指定參數(shù)為空的默認的構造函數(shù)。子類中也定義了一個帶整型參數(shù)的構造函數(shù)。編譯時,編譯器將試圖在子類的構造函數(shù)中調用父類的參數(shù)為空的構造函數(shù),但是父類中沒有定義參數(shù)為空的構造函數(shù),所以編譯程序將會報錯。排錯的方法時在子類的構造函數(shù)中顯示調用父類的構造函數(shù),或者在父類中添加一個帶空參數(shù)的構造函數(shù)。




























???排錯方法1:



























???排錯方法2:



































二、類方法和實例方法在繼承過程中的問題:
???
???首相要明確一個概念,JAVA中通過什么來區(qū)別不同的成員——答案是標記。所謂標記,對于方法而言是指方法的名字、參數(shù)的數(shù)量和參數(shù)的類型;對于變量而言是指變量的名稱。注意,標記不包括方法的返回值和變量的類型。
???如果子類的實例方法和父類的實例方法具有相同的標記,子類的方法將覆蓋父類的方法。但是如果子類的方法和父類的方法具有相同的標記,但是具有不同的返回值類型,編譯程序將會報錯。排錯的方法是修改子類中這個方法的返回值類型,使它父類中相同標記的方法的返回值一樣。






















???排錯:






















???同樣如果子類的類方法和父類的類方法具有相同的標記,那么子類的類方法將隱藏父類的類方法。注意這里不叫覆蓋,而叫隱藏,兩者的區(qū)別將在后面討論。同樣,如果子類的類方法和父類的類方法具有相同的標記和不同的返回值,編譯程序也會報錯。解決的問題的方法同實例方法一樣。
???但是實例方法不能覆蓋類方法,類方法也不能隱藏實例方法,否則編譯程序就會報錯。
???
???實例方法不能覆蓋類方法(編譯時報錯):






















???類方法不能隱藏實例方法(編譯時報錯):






















???覆蓋和隱藏的區(qū)別。對于隱藏的方法,運行時系統(tǒng)調用當前對象引用的編譯時類型中定義的方法;對于覆蓋的方法,運行時系統(tǒng)調用當前對象引用運行時類型中定義的方法。一個是調用編譯時類型中定義的方法,一個是調用運行時類型中定義的方法。通過下面這個例子可以直觀的看出兩者之間的差別。








































???Earth類覆蓋了Planet類的override方法,并隱藏了它的hide方法。在main方法中創(chuàng)建了一個Earth的實例,并將此實例轉換為一個Planet的引用。然后通過Planet引用調用override方法和hide方法。hide方法是類方法,因此根據(jù)引用的類來決定調用哪個方法,所以planet.hide()調用的是Planet的類方法hide。override方法是實例方法,因此調用的是運行時的實例中的方法,因為planet引用的是Earth的實例,因此planet.override()調用的是Earth類中實例方法override。
???JAVA正是通過實例方法的這種覆蓋關系來實現(xiàn)多態(tài)的目的。
三、類的變量在繼承過程中的問題:
???
???如果子類中的變量如果和父類中的變量具有相同的標記——即相同的名字——那么子類中的變量一就會隱藏父類中的變量。不過他們的類型是什么,也不管他們是類變量還是實例變量。只要他們具有相同的名字。

















???同子類中的類方法隱藏父類中的類方法一樣,當子類中的變量覆蓋父類中的變量的時候,到底使用哪個變量,要根據(jù)引用的類型來確定。
???下面是一個類成員繼承關系的綜合例子:



























































