2011-07-29 50 views
2

在超類A和子類B中,我分別將變量abc分別設置爲10和20,並在子類中重寫一個方法callme()。爲什麼java ref vars根據實際對象調用方法,因爲變量基於ref變量類型?

,如果我做

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

然後如果我寫

a.callme() -> calls B's method 
b.callme() -> calls A's method. 

這是因爲方法是基於實際的對象調用。

,如果我做

str = a.abc; // will print 10 , based upon ref var type A 

str = b.abc; // will print 20 , based upon ref var type B 

爲什麼這種差異?爲什麼不能根據實際對象訪問方法和變量?

感謝

回答

2

記住,實例變量從未overidden,他們是隱藏。這是決定訪問其實例變量的引用類型。

在子類中,方法callme()已過時。因此,根據動態方法調度機制,它是決定在運行時將調用哪種方法的對象類型。這是因爲,對象是在運行時創建的。

E.g

class A { 
     int abc = 10; 

     public void callme() { 
      System.out.println("In class A"); 
     } 
    } 

class B extends A { 
     int abc = 20; // hidden, not overidden 

     public void callme() { 
      System.out.println("In class B"); 
     } 

     public static void main(String [] args) { 
     A a = new A(); 
     a.callme(); // calls A's callme() method. 

     B b = new B(); 
     b.callme(); // calls B's callme() method. 
     } 
} 
+0

一些來自甲骨文的Java教程]隱藏字段說明(http://download.oracle.com/javase/tutorial/java/IandI/hidevariables.html) –

+0

,我知道這一點。子類實例變量隱藏具有相同名稱的超類變量。 –

+0

我想我不能清楚地問清楚,我知道這些字段是隱藏在子類字段中的。這是一個合理的答案,也是正確的。我想問問爲什麼基於對象ref變量類型和實際對象類型調用方法和字段?這與某些方法和領域將如何存儲在內存中有關嗎?任何人都可以解釋嗎? –

0

方法已經實現,而只是字段的值存儲/對象。能夠重寫方法的實現是有意義的。但我認爲沒有必要「超越」一個領域。爲什麼不要從子類中刪除聲明並使用超類的字段?

另一方面也可以隱藏方法。但是你必須讓它們保密。

class OuterClass { 
    void test() { 
     InnerSubClass isc = new InnerSubClass(); 
     isc.m(); // prints "In subclass" 
     ((InnerSuperClass) isc).m(); // prints "In superclass" 
    } 
    class InnerSuperClass { 
     private void m() { 
      System.out.println("In superclass"); 
     } 
    } 
    class InnerSubClass extends InnerSuperClass { 
     private void m() { 
      System.out.println("In subclass"); 
     } 
    } 
} 
相關問題