2013-03-09 178 views
0

我對Java類實現的抽象方法簽名頗感困惑。Java抽象方法簽名

例如,請考慮:

interface Programmer { 
    Object program(); 
} 

class Linus implements Programmer { 
    public String program() { 
     return "goto end;"; 
    } 
} 

public class Main { 
    public static void main(String[] args) { 
     System.out.println(new Linus().program()); 
    } 
} 

這顯然是可以接受的,因爲任何希望的對象來自Linus.program()將獲得一個(具體來講,字符串)。

但是現在考慮這個問題:

interface OS { 
    void run(String code); 
} 

class Linux implements OS { 
    public void run(Object code) { 
     System.out.println("Hello world"); 
    } 
} 

public class Main { 
    public static void main(String[] args) { 
    new Linux().run("print 'Hello world'"); 
    } 
} 

這編譯失敗,併產生錯誤:

The type Linux must implement the inherited abstract method OS.run(String) 

現在,什麼事情都可能期望能夠將字符串傳遞到的任何實例OS界面,你當然可以用Linux來做到這一點。

我沒有看到第二個編譯失敗的原因。使用Java編譯第二個程序的後果,我錯過了一些令人望而卻步的東西嗎?

回答

5

你正在爲第二種情況做的是方法超載。
方法的簽名是「方法名稱」和「參數的數量和類型」
在第二種情況下,您正在更改參數的類型,其中編譯器是另一種方法,並要求您實現抽象(未實現)方法。如果您實現接口public void run(String code)中的方法,則此方法public void run(Object code)將被視爲重載方法。

注意:方法覆蓋從不基於方法的返回類型。由於返回類型不被視爲方法的簽名

+3

超載,不重寫...... – 2013-03-09 09:07:29

+0

@OliCharlesworth感謝您糾正:) – asifsid88 2013-03-09 09:08:40

0

您不能傳遞基類Object的實例來代替類String的實例,但反之有效。在你的界面操作系統中,run方法的參數是String類型的,而在實現類中,你將這個參數概括爲不允許的Object類型。因此,編譯器抱怨。

+0

這並不能解釋它。我正在調用Linux基類。如果我正在調用操作系統界面,那麼這一點是有效的。 Linux基類接受所有對象,包括字符串。 – 2013-03-16 02:27:17

+0

底線是您無法更改接口強制執行的合同中的參數。在這裏,您將參數的類型從String更改爲Object,這在技術上使其成爲新的方法定義,而不是接口合同的實現,因此也是錯誤。 – Drona 2013-03-21 07:56:58

0

你說:「現在,任何事情都可能會傳遞一個字符串到操作系統接口的任何實例中,你當然可以用Linux來做到這一點。」 =>問題是你可以,但不是必需的。

考慮一下:例如,Linux版本的方法將Object作爲參數,您可以嘗試傳遞一個Collection。因此,你不會尊重界面,它明確地將參數限制爲一個字符串。這就是Linux版本的方法不被認爲是操作系統版本的「孩子」的原因。

而作爲接口中的每個方法都需要有「兒童」,編譯器會抱怨你沒有實施OS.run(String)將「孩子」

+0

那麼,那些模糊或者無法工作的代碼是什麼? – 2013-03-18 17:08:41