2017-04-26 109 views
4

這個問題來自AP計算機科學實踐考試。爲什麼這個對象可以訪問父類的方法?

public class Bird 
{ 
    public void act() 
    { 
     System.out.print("fly"); 
     makeNoise(); 
    } 
    public void makeNoise() 
    { 
     System.out.print("chirp"); 
    } 
} 

public class Dove extends Bird 
{ 
    public void act() 
    { 
     super.act(); 
     System.out.print("waddle"); 
    } 
    public void makeNoise() 
    { 
     super.makeNoise(); 
     System.out.print("coo"); 
    } 
} 

假設下面的聲明出現在類以外的其他鳥或鴿子:

Bird pigeon = new Dove(); 

什麼是印刷作爲呼叫pigeon.act()的結果?

我認爲答案是「飛唧唧」,但教科書說答案是「飛啾咕coo蹣跚」。我認爲'鴿子'只能訪問Bird中可用的方法?我的印象是,如果用戶想要訪問鴿子的方法,鴿子就必須投向鴿子。

Bird pigeon = new Bird();會給出相同的輸出嗎? Dove pigeon = new Dove();怎麼樣?

+0

任何類都可以使用'super'關鍵字明確調用其父方法。 –

+0

我瞭解super關鍵字的功能。我的問題是爲什麼「鴿子」可以訪問鴿子的方法。我認爲「鴿鴿=新鴿」();「會產生「飛啁啾coo蹣跚」。 –

+0

提示:手動調用'pigeon.makeNoise()'並觀察會發生什麼。 – biziclop

回答

1

從你的問題後,「我認爲,‘鴿子’只能訪問鳥類可用的方法?我的印象是,如果用戶想訪問鳩方法, '鴿子'必須投給鴿子。「這實際上是true

讓我們試着在理解中找到mssing鏈接。

  1. 當我們有一個像Bird pigeon = new Dove();代碼,其中Dove延伸Bird我們有Dove實際對象和引用類型是Bird。由於目標是Dove所以它有方法,繼承從超級以及增加

  2. 另一個重要的點是所有的overriden方法只有一個實例。它的Overriden意味着同一個方法的行爲已被修改,它不是一個額外的單獨方法。只有一個繼承方法的副本不是兩個。它的重載方法是分開的,只是名字相同但簽名不同。這是您在調用任何重寫方法時獲得Dove行爲的原因。

  3. 這一個很簡單super,使用它的子類可以訪問其超類的可訪問(可見)實體(實例屬性和方法)。如果子類使用super關鍵字來調用一個方法,那麼它的被調用的父類的方法。但是可以認爲,這個子類的作者也是故意的。一旦寫入了類並且創建了此類的對象,然後在使用.(點運算符)的對象上,用戶只能調用對象中的那些對象。如果有任何方法使用關鍵字super其對象的部分行爲。 Sub類對象的用戶如果在子類中重寫它,則不能調用父類方法的行爲。

  4. 最後是,如果你想使用Bird(超類)的參考,那麼你需要將它轉換爲Dove調用Dove(子類)的任何其他方法。

4

長話短說,當您訪問的pigeonact方法,從Dove它的覆蓋被調用。

我以爲'鴿子'只能訪問Bird中可用的方法嗎?

至少在沒有應用鑄造的情況下,這當然是正確的。然而,方法act可用於類Bird,這是靜態已知類型的pigeon,因此調用編譯良好。

但是,訪問方法只是關於能夠調用它們。當你打電話給他們時,什麼方法是在運行時根據動態類型pigeon決定的。這是方法重寫的地方,因爲Dove覆蓋Bird的方法,但此外它還調用Bird的方法。這就是爲什麼代碼打到全部四個打印輸出。

Bird pigeon = new Bird();會給出相同的輸出嗎?

否,則輸出將是不同的,因爲在這種情況下,動態和靜態類型的pigeon將是相同的,即Bird,所以只有Bird的實施方式將被調用。

+5

這也是爲什麼你永遠不能從構造函數調用overrideable方法的原因,因爲子類可能會覆蓋它,使得構造函數變得脆弱並且可能不安全。 – biziclop

2

你在這裏遇到的是多態性在行動。而不是直接回答你的各種問題;我會簡單解釋你正在觀察的情況。

您在Dove的實例上致電act();導致超級呼叫;印刷「飛」。

超級方法然後調用makeNoise() ...關於「本身」。但正如所說:「本身」是一個鴿子對象;因此你得到鴿子噪音! 「COO」!

然後Dove實現結束;並打印「蹣跚」。

本質是:時調用在運行時被確定的方法的精確版本,它僅取決於確切類型的方法被調用的對象的。

上面給你全部你需要自己回答你的其他問題的信息。從這個意義上說:不要求答案;請求解釋;並用它們來解決這個難題!

2
  • Dove確實覆蓋方法actBirdmakeNoise。覆蓋意味着將方法可見的的行爲更改爲子類(在您的情況下爲Dove)。如果子類具有publicprotected訪問修飾符,或者它們具有package private訪問修飾符,並且子類與超類屬於同一個包,則方法對子類可見。
  • pigeonDove的一個實例。
  • 致電pigeon.act()結果致電Dove.act
  • Dove.act來電super.act這是Bird.act
  • Bird.act打印fly並致電makeNoisepigeon導致致電Dove.makeNoise
  • Dove.makeNoise來電super.makeNoise這是Bird.makeNoise
  • Bird.makeNoise print chirp
  • Dove.makeNoise打印coo調用super.makeNoice
相關問題