2013-03-25 3 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

+0

Что вы получаете, когда пытаетесь? –

ответ

3

Это не очень JVM, а компилятор Java. (Если JVM находит отсутствующий метод, который должен быть там, вы получаете исключение NoSuchMethodException, но компилятор не позволит вам добраться до этой точки, если вы не обманете его).

Что касается вашего вопроса, не имеет значения, какой класс или суперкласс или интерфейс объявлен в методе, необходимо совместить только имя и подпись. Таким образом, ActionCharacter#fight и CanFight#fight объявляют то же самое. Java не делает различий между ними (ни компилятор, ни формат JVM/байт-кода).

Ваш Hero наследует fight от ActionCharacter, но так как это происходит также соответствовать методу, определенный в CanFight, он также служит реализации этого интерфейса.

Может быть более ясным или изменить имя метода (если предполагается, что это два разных метода) или ActionCharacter также реализовать CanFight (если это действительно предназначено для того же метода).

+0

так это провал или особенность? – Rorschach

+0

Зависит от вашей точки зрения. Разумеется, это не позволяет вам определять два семантически разных интерфейса метода с тем же именем и сигнатурой. Но тогда вы, вероятно, должны выбрать лучшие имена. – Thilo

1

Вы распространяете ActionCharacter, что означает, что вы хотите, чтобы все операции и атрибуты ActionCharacter унаследовали ваш класс Hero.

Включает в себя операцию fight. Вы отмечаете Hero как реализующий CanFight, но вы наследуете фактическую реализацию от ActionCharacter.

+0

Почему он не бросает ошибку, когда я не участвую в битве, хотя реализую интерфейс canFIght? – Rorschach

+0

Это как вы (Герой) наследуете все ваши деньги от вашего Отца (в данном случае ActionCharacter), так что теперь у вас есть операция isRich внутри вас, хотя все деньги, которые вы получили от своего отца. Хотя вы их не зарабатывали, у вас есть деньги, поэтому вы богаты. Надеюсь, это поможет :) – shazin

+1

@shazin: проблема с этим, конечно, в том, что идея ActionCharacter о «богатых» полностью не связана с этим интерфейсом. – Thilo

0

Герою требуется реализовать void figth();, но он наследует void figth(); от ActionCharacter, поэтому требование выполнено.

+0

проблема с этим (и, я думаю, точка вопроса) заключается в том, что вы намеревались использовать два этих семантически разных метода. Java (ни компилятор, ни JVM) не могут разделить их. – Thilo

0

Интерфейсы только объявляют метод, вы не можете определить метод в интерфейсе. Так что это означает, что вы даете проект того, что вы хотите реализовать в интерфейсе.

Теперь ваш герой класса наследует класс ActionCharacter, который имеет определение public void fight(). Однако этот бой() не связан с борьбой() CanFight. поэтому, если вы определяете бой() в Hero, вы отмените бит() ActionCharacter.

Поскольку вы также реализуете интерфейс CanFight, jvm позволит это, поскольку вы объявили метод в CanFight, но он будет рассматриваться как переопределение боя() ActionCharacter.

2

Если тип реализует два интерфейса, и каждый интерфейс определяет метод, имеющий идентичную подпись, тогда на самом деле существует только один метод, и они не различимы.

Если, скажем, два метода имеют конфликтующие типы возврата, то это будет ошибка компиляции. Это общее правило наследования, переопределения метода, скрытия и деклараций, а также относится к возможным конфликтам не только между двумя унаследованными методами интерфейса, но также интерфейсом и методом суперкласса или даже просто конфликтами из-за стирания типов дженериков ,

Сказано в JLS

Разрешается для одного объявления метода в классе реализовать методы более одного суперинтерфейса.

Смежные вопросы