2013-03-25 48 views
3
interface CanFight { 
    void fight(); 
} 

interface CanSwim { 
    void swim(); 
} 

interface CanFly { 
    void fly(); 
} 

class ActionCharacter { 
    public void fight() { 
     System.out.println("Inside class fight"); 
    } 
} 

class Hero extends ActionCharacter 
    implements CanFight, CanSwim, CanFly { 
    public void swim() {} 
    public void fly() {} 
} 

     public class MultipleInterface { 
    public static void t(CanFight x) { x.fight(); } 
    public static void u(CanSwim x) { x.swim(); } 
    public static void v(CanFly x) { x.fly(); } 
    public static void w(ActionCharacter x) { x.fight(); } 
    public static void main(String[] args) { 
    Hero h = new Hero(); 
    t(h); // Treat it as a CanFight 
    u(h); // Treat it as a CanSwim 
    v(h); // Treat it as a CanFly 
    w(h); // Treat it as an ActionCharacter 
    } 
} 

如何JVM表現得像我不是從canFight接口的實現方法,但它需要從ActionCharacter類?它背後的邏輯是什麼?要點是我沒有定義方法fight(),如果實現canFight()接口必須完成。如何JVM對此有何反應

+5

試試看! SO不是一個你可以簡單嘗試看的問題! – Varun 2013-03-25 06:17:28

+0

當你嘗試時會得到什麼? – 2013-03-25 06:18:52

回答

3

這不是JVM的多少,而是Java編譯器。 (如果JVM找到一個應該在那裏的方法,你會得到一個NoSuchMethodException,但編譯器不會讓你到那個地步,除非你欺騙它)。

至於你的問題,聲明哪個類或超類或接口方法並不重要,只有名稱和簽名需要匹配。因此,ActionCharacter#fightCanFight#fight宣告同樣的事情。 Java不區分這兩者(無論是編譯器還是JVM /字節碼格式)。

Hero繼承ActionCharacterfight,但因爲它正好也匹配CanFight定義的方法,還兼作該接口的實現。

可以更清楚地更改方法名稱(如果這些方法應該是兩種不同的方法),或者0123也可以實現CanFight(如果這實際上旨在是相同的方法)。

+0

所以它是一個失誤或功能? – Rorschach 2013-03-25 06:22:11

+0

取決於你的觀點。可以肯定的是,它可以防止您定義兩個具有相同名稱和簽名的語義不同的方法接口。但是,你應該選擇更好的名字。 – Thilo 2013-03-25 06:23:36

1

您正在擴充ActionCharacter這意味着您需要將ActionCharacter的所有操作和動態屬性繼承自Hero這個類。

這也包括fight的操作。您將Hero標記爲CanFight,但您繼承ActionCharacter的實際實施。

+0

爲什麼它不會在執行canFIght接口時發生錯誤? – Rorschach 2013-03-25 06:21:24

+0

它就像你(英雄)從你父親那裏繼承你所有的錢(在這種情況下是ActionCharacter),所以你現在在你內部進行了很好的操作,儘管你所有的錢都來自你的父親。儘管你沒有賺到錢,但你有錢,所以你很有錢。希望這有助於:) – shazin 2013-03-25 06:24:09

+1

@shazin:這個問題當然是如果ActionCharacter的「富」的想法是完全無關的接口。 – Thilo 2013-03-25 06:25:21

0

英雄需要執行void figth();,但它從ActionCharacter繼承void figth();,以滿足要求。

+0

這個問題(我想這個問題的重點)是如果你打算這兩個是兩個語義上不同的方法。 Java(無論是編譯器還是JVM)都不能將它們分開。 – Thilo 2013-03-25 06:26:58

0

接口只聲明一個方法,你不能在一個接口中定義一個方法。所以它意味着你要給一個你想在界面中實現的草稿。

現在在這裏,你的類Hero繼承了具有public void fight()定義的類ActionCharacter。然而,這場戰鬥()與CanFight的戰鬥()沒有任何關係。所以如果你在Hero中定義了一個fight(),你將覆蓋ActionCharacter的fight()。

既然你也實現了CanFight接口,那麼jvm會允許你這樣做,因爲你已經在CanFight中聲明瞭方法,但是它將被視爲ActionCharacter的fight()的覆蓋。

2

如果一個類型實現了兩個接口,並且每個接口定義了一個具有相同簽名的方法,那麼實際上只有一個方法,並且它們是不可區分的。

如果說,這兩種方法有衝突的返回類型,那麼這將是一個編譯錯誤。這是繼承,方法重寫,隱藏和聲明的一般規則,並且也適用於不僅在2個繼承的接口方法之間,而且也在接口和超類方法之間的可能衝突,或者甚至僅適用於泛型的類型擦除造成的衝突。

它在JLS

它允許一個單一的方法聲明一個類來 實現多個超接口的方法說。