2017-10-28 295 views
-1

動態綁定和構造函數鏈之間的困惑按照書上的我下面,下面的代碼打印:在Java

public class DynamicBindingDemo { 
    public static void main(String[] args) { 

    m(new graduateStudent()); 
    m(new Student()); 
    m(new Person()); 
    m(new Object()); 
} 

    public static void m(Object x) { 
    System.out.println(x.toString()); 
    } 
} 

    class GraduateStudent extends Student { 
    } 

    class Student extends Person { 
     public String toString() { 
     return "Student"; 
    } 
} 

    class Person extends Object { 
    public String toString() { 
    return "Person"; 
    } 
} 

打印:

學生

學生

[email protected]

有人可以幫我解釋爲什麼嗎?在這裏,我如何跟蹤代碼:

因此,m(new graduateStudent())調用m(Object x)的多態調用時,x.toString()由GraduateStuent類而不是Object類調用,因爲GraduateStuent是實際對象的類型。在可以在GraduateStudent類中調用x.toString()之前,編譯器會在GS類中隱式創建一個無參數構造函數,因爲沒有它。但是,在調用此構造函數之前,首先會調用學生類構造函數,因爲它是超類。學生構造函數是在學生類中創建的(因爲它沒有),但是在構造函數被調用之前,人類構造函數被調用,因爲它是超類等等直到我們到達Object超類,並且它的字符串方法應該被調用。 ...

我很確定我在很多事情上是錯的(我是一個2個月的大學新生,這是一個小課程)。那麼有人可以解釋我出錯了嗎?

+0

方法重載你似乎完全混爲一談構造和動態綁定的想法。當你調用'toString()'(這是不必要的,順便說一下,因爲'println(Object)'會爲你做),構造函數就完成了。您可以完全消除問題其餘部分對構造函數的討論。看看這是否足夠簡化它是有道理的。 – chrylis

回答

0

調用哪個方法不依賴於構造函數的執行。 然而,有一個技巧,父的構造函數作爲子構造函數的第一步執行。它將被編譯器添加,除非明確添加。例如。學生的構造函數如下所示:

public Student() { 
    super(); //parent initialised before child 
} 

實際上你做的是重寫方法。

您可以考慮覆蓋任何父類中的方法。 另外要了解這一點,你可以想到繼承鏈: 畢業生 - >學生 - >人 - >對象

在鏈中找到的第一個toString方法將被調用。實際上這個版本用於原型繼承,在java中它的實現方式不同。但是爲了理解它應該是足夠的。

所以對於你例子:

  • 你是不是覆蓋父Student類的父類的方法使學生的方法被稱爲
  • 學生覆蓋人toString方法,學生的方法被稱爲
  • 人覆蓋對象的toString方法,人的方法被稱爲
  • 對象的toString被調用,因爲它沒有父類,並且包含方法toString。

你可以閱讀更多有關在互聯網:)