2012-09-16 121 views
0

的這個簡單的例子,請看看下面的代碼:混淆多態性

class Foo { 
    public int a; 
    public Foo() { 
     a = 3; 
    } 
    public void addFive() { 
     a += 5; 
    } 
    public int getA() { 
     System.out.println("we are here in base class!"); 
     return a; 
    } 
} 

public class Polymorphism extends Foo{ 
    public int a; 
    public Poylmorphism() { 
     a = 5; 
    } 
    public void addFive() { 
     System.out.println("we are here !" + a); 
     a += 5; 
    } 
    public int getA() { 
     System.out.println("we are here in sub class!"); 
     return a; 
    } 

    public static void main(String [] main) { 
     Foo f = new Polymorphism(); 
     f.addFive(); 
     System.out.println(f.getA()); 
     System.out.println(f.a); 
    } 
} 

在這裏,我們分配Polymorphism類對象的引用Foo型,經典polmorphism的變量。現在我們調用Polymorphism中已被覆蓋的方法addFive。然後我們從getter方法中打印變量值,該方法也已在類Polymorphism中被覆蓋。所以我們得到答案爲10.但是,當公開變量a是SOP'ed我們得到答案3!

這是怎麼回事?儘管引用變量類型是Foo,但它指的是多態類的對象。那麼爲什麼訪問f.a不會導致打印類Polymorphism中的a值?請幫忙

回答

2

這是由於這樣的事實,你不能覆蓋類可變因素。當訪問一個類變量時,引用的類型而不是對象的類型決定了你會得到什麼。

如果刪除的重複聲明將在子類中,那麼我認爲這種行爲會更加符合市場預期。

+0

ohh ..那麼你能不能解釋我爲什麼是這樣?我的意思是,如果變量也被覆蓋,那麼可能會產生什麼影響?因爲檢查對象類型,同時調用mmethods和檢查類的類型,同時讓字段聽起來很奇怪 – Shades88

+0

我可以嘗試;)引用類型決定哪些方法和變量可用於調用。你用多態性做的是重寫這些可用方法的**行爲**。但是,由於您無法覆蓋類變量,您將始終在引用類型的類中獲取該變量的值。 – Tobb

5

你在隱藏aPolymorphism - 你實際上應該得到一個編譯器的警告。因此這些是兩個不同的a字段。與方法相反,字段不能是虛擬的。好的做法是根本不公開領域,但只有變異私有狀態的方法(封裝)。

如果你想讓它虛擬的,你需要使它與存取方法的屬性(例如你有什麼:getA)。

+0

一兩件事,可能潛在澄清這是仰視「阿爾法重命名」,這是什麼道德上發生在這裏的定義。 –

+0

爲什麼在獲取字段時檢查調用方法和類類型時是否檢查了對象類型?如果變量也被對象類型引用,結果會是什麼? – Shades88

+0

是的我明白變量不應該公開。它在代碼中僅用於測試:) – Shades88