2013-02-17 115 views
1

我有一些像這樣的代碼:爲什麼Java不會編譯這段代碼?

abstract class ExampleOne { 
    int dataOne = 1000; 

    abstract void display(); 
} 

class ExampleTwo extends ExampleOne { 
    int dataTwo; 

    ExampleTwo(int varOne) { 
     dataTwo = varOne; 
    } 

    public void disp() { 
     System.out.println("Testing"); 
    } 

    public void display() { 
     System.out.println(dataOne); 
    } 
} 

class Example { 
    public static void main(String args[]) { 
     ExampleOne obj = new ExampleTwo(20); 
     obj.disp(); 
     obj.display(); 
    } 
} 

當我編譯此,我得到一個錯誤:

   obj.disp(); 
        ^
    symbol: method disp() 
    location: variable obj of type ExampleOne 

爲什麼會出現這種情況?

我將ExampleTwo的實例分配到ExampleOne,爲什麼Java不選擇ExampleOne實例而不是ExampleTwo

同樣的概念在dynamic polymorphism方面有效!

這是爲什麼?

回答

9

由於obj類型是ExampleOne,編譯器將搜索您在ExampleOne類上obj調用該方法,如果找不到,就會拋出一個錯誤。

why doesn't Java choose the ExampleOne instance instead of ExampleTwo?

這是因爲編譯時檢查引用類型而非實際對象類型的基礎上完成的。然後在運行時調用的實際方法根據被引用的實際對象決定。這就是我們所說的方法調用的動態調度

您可以將一個抽象disp()方法添加到您的ExampleOne類中,只是爲了確保編譯器對調用滿意。

abstract class ExampleOne{ 
    int dataOne=1000; 
    abstract void display(); 
    abstract void disp(); 
} 
4

你的方法是隻在ExampleTwo定義,但不ExampleOne。這會導致編譯錯誤。

+0

這是不正確的..在運行時**這將是'ExampleTwo' ..錯誤是因爲編譯器無法在編譯時找到該方法 – Anirudha 2013-02-17 07:41:00

1

您的對象類型是ExampleOne。即使您創建了ExampleTwo的實例,編譯器已知的對象類型(即方法和成員)也是ExampleOne,它們沒有聲明disp()。

你應該ExampleOne如果你想在一個多態的方式

1

基類對象只能訪問自己的類Methods使用聲明的抽象方法disp()。但disp()不是它的方法。所以這就是你得到錯誤的原因。

,以避免錯誤,你可以這樣做:

ExampleTwo obj=new ExampleTwo(20); 
        obj.disp(); 
        obj.display(); 
1

好,

背後的理念是,通過該Java contruct,你會調用ExampleOne的方法與ExampleTwo的版本。

表示只允許您調用引用變量類型的方法(在您的情況下,它是ExampleOne)。但是,調用的方法的版本將是基礎對象類型(即ExampleTwo)。並且由多態性促進。

這裏值得一提的是,您可以將對象分配給任何其類型的引用變量或其任何超類,在層次結構中。