2016-02-15 56 views
0
public class A { 

    public void m1(A a) { 
     System.out.println("m1(A) in A"); 
    } 

    public void m4() { 
     System.out.println("m4() in A"); 
    } 
} 

public class B extends A{ 

    public void m1(B b) { 
     System.out.println("m1(B) in B"); 
    } 

    public void m4() { 
     System.out.println("m4() in B"); 
    } 

} 

public class Test { 

    public static void main(String[] args) { 

     B b = new B(); 
     A a = b; 
     a.m1(b); // returns m1(A) in A 
     a.m4(); // returns m4() in B 
    } 

} 

有人能解釋爲什麼a.m1(b)使用A的方法,而a.m4()使用B的方法嗎?在java中動態綁定方法 - 爲什麼這個方法?

我特別不明白這個變量(a)是如何調用兩個不同類的方法的。我認爲,在運行時,a要麼視爲A或B,然後應導致從A兩種方法或B.

回答

1

讓我們從對象聲明的基礎入手。

讓我們考慮一個類Animal

Animal anim=new Animal(); 

Anim anim告訴JVM建立類型動物的新的參考變量和new Animal()詢問JVM以創建新的Animal對象。這兩個語句結合=告訴JVM創建一個Animal類型的引用變量,併爲它分配一個動物對象。

什麼是anim

  • anim類似於控制Animal類型的對象的行爲的遙控器。我們用它來指代對象。

我希望現在清楚。

現在讓我們繼續繼承和多態。考慮一個新的類Dog,它延伸AnimalDog成爲Animal的子類。

如果繼承,您可以考慮IS A規則。在這種情況下,由於Dog已延長Animal,Dog IS A Animal。我希望你得到了我。這是多態性進入圖片的地方。多態性意味着您可以實際使用超級類引用變量來引用子類對象。

Animal anim1=new Dog(); 

我們已經創建了一個遙控anim1其控制Dog對象。這個anim1參考(遙控器)只能控制AnimalDog的具體方法。這個遙控器還可以控制過度使用的方法,但不能控制Dog中沒有繼承或覆蓋的任何新方法。

現在,讓我們繼續前往您的課程ABB IS-A A,因爲它擴展了A

這意味着A a= new B();是多態的。這是類似於YOH已經使用下面的代碼完成:

B b=new B(); 
A a=b; 

現在爲什麼a.m1(b);轉到方法在Aa.m4();B

讓我們其他人去之前看的東西:

你有A類的方法: public void m1(A a)

你有B類的方法: public void m1(B b)

重寫意味着你實際上在子類中重新定義了一個繼承的方法。所以在你的情況下,m1(B b)B類沒有超越,因爲它具有不同的paraneter。它具有的參數類型爲B,而原始m1(A a)A中查找類型爲A的參數。簡而言之,您的類B有兩種方法,分別命名爲m1。 從A繼承的一個和參數類型爲B的新方法或過載方法。

就像我已經提到的,我們的遙控器a只能看到類A特定的方法。它看不到過載的方法。這就是原因,它實際上是繼承了方法m1(A a)

現在,a.m4();轉到m4()B。爲什麼?

  • 因爲在Bm4()是過深重的方法和a可以看到它。

假如你叫b.m1(b),將被用於B方法。

總結: 您可以使用超級引用變量/ remote來引用/指向子類對象,但此遠程只能看到繼承的方法,包括過度使用但未超載。 但是,子類型的引用將能夠看到所有的方法。

爲了幫助您識別過度纏身和重載的方法:

過纏身的方法是這樣的:

  • 參數必須是相同的,參數必須相同或兼容。
  • 方法不能少訪問。那就是public不能做成private

重載的方法,如:

  • 返回類型可以是不同的。

  • 參數類型或參數的數量應該有所不同。

  • 訪問級別是可以改變的

使用上面的規則,你可以輕鬆地idebtify是m1(B b)B實際上是一個重載的方法,因爲參數類型從m1(A a)變化。

最後,B擁有3種方法:

  • m1(A a) inherted

  • m1(B b)超載

  • m4()過纏身

請評論,如果您有任何疑問或一個例子錯誤。

+0

哇。非常感謝你的努力!我的錯誤是假定m1(B b)是一個覆蓋,因爲每個B也是一個A.但現在它實際上是有道理的,事實並非如此。很好的答案! – Daniel

+0

我很高興它幫助你。快樂學習。 –

4

這兩種方法那是因爲B.m1(B)不會覆蓋A.m1(A)。這是一個重載,因爲它的參數是不同的類型。

爲了覆蓋它,您需要將參數類型更改爲A

注意,它總是一個好主意,註釋你與@Override重寫你想方法:那麼編譯器會告訴你,如果你沒有真正覆蓋方法。

還要注意的是,如果你叫b.m1(b);呼籲B的方法,因爲這是超載更具體的說A.m1(A)。然而,使用當前代碼,在編譯時可以匹配的唯一方法是A.m1(A),因爲衆所周知的是aA的一個實例或它的一個子類型:已知可用的唯一方法是方法在A

調用的方法在編譯時選擇,而不是運行時。

+0

但是爲什麼a.m4()返回B方法的消息? – Daniel

+0

因爲*是重寫'A.m4()'。它具有相同的參數(都爲零)和相同的返回類型('void')(嚴格來說,返回類型不需要完全匹配:重寫方法的返回類型必須與重寫方法的協變)。 –

+0

因此,因爲'a'是一個形式A,所以首先看A中的方法。因爲B中的方法m1具有與A中的方法不同的參數類型(儘管B中的參數類型實際上更適合) ,選擇A中的方法。對於m4(),選擇B的方法,因爲它覆蓋A中的方法,'a'是引擎蓋下的B。是對的嗎? – Daniel

相關問題