2013-11-12 4 views
4

Предположим, у вас есть два интерфейса I1 и I2 оба интерфейса имеют один и тот же методУточнить концепцию множественного наследования: может возникнуть проблема с структурой бриллианта?

1)public int add(int a) throws exception e1 //(Interface 1) 

2)public int add(int a) throws exception e2 //(Interface 2) 

теперь класс реализует как I1 и I2.

@override 
public int add(int a) exception e1 
{ 
//adding operation 
} 

Примечание: Я понимаю, что если реализовать несколько интерфейсов, которые имеют тот же метод, то только одна реализация будет там в реализующем классе.

  1. ли компилятор делать вывод, является ли этот метод от I1 или I2 на основе бросках положение? Требуется ли уточнение подписи метода? (Я знаю, что подпись включает имя и параметры, переданные.)

  2. Если мы реализовали оба интерфейса, а затем мы выбрасываем только e1, компилятор разрешит это, поскольку класс реализации на самом деле не реализует оба интерфейса? это вызовет бриллиант структура проблема?

  3. Нужно ли реализовать тот же метод с предложением throws e1 и 2-е время e2? Когда я попробовал это, компилятор сказал мне, что у меня есть повторяющиеся методы.

  4. Если мы реализуем первый I1, тогда он говорит, что это метод I1, и если мы сначала напишем I2, тогда он скажет свой метод I2. Объясните, почему это так.

+1

Функция реализации должна реализовывать все интерфейсы. Это может потребовать от него исключения * исключений *. –

+0

@Kerrek SB: Не могли бы вы немного рассказать о «Это может потребовать, чтобы он не выдавал никаких исключений». Я говорю, что класс реализовал только один метод без исключения? так что сказать? Метод I1 + метод I2? Или, если он пишет throws e1, компилятор знает, что этот метод от I1? ** Спасибо –

+0

Что ты говоришь? Что означает «это должно сказать»? Кто должен сказать? Скажи когда? – EJP

ответ

7

Интерфейс определяет договор. Если интерфейс определяет метод

void foo() throws SomeException; 

тогда он говорит: все исполнители классы должны иметь метод Foo, возвращая пустоту, не принимая никаких аргументов, и который позволил бросить SomeException но никакого другого типа checkd исключения ,

Метод реализации может, конечно, не исключать какого-либо исключения вообще, поскольку он не будет нарушать договор метода интерфейса. throws означает: этот метод может вызвать это исключение в некоторых случаях.

Таким образом, метод объявлен как

public void foo(); 

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

Таким образом, в вашем примере,

public int add(int a) throws Exception1 

является допустимым объявление метода для переопределения

int add(int a) throws Exception1 

но не действительны для

int add(int a) throws Exception2 

(если конечно Exception1 является подклассом Exception2).

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

+0

Спасибо за ваш интерес :), но если я напишу int add (int a), то выкидывает Exception2 и при реализации интерфейса className реализует I2, I1 в этот момент он говорит о методе I1 для реализации? как это происходит? из-за заказа? I2 реализован первым? действительно ли это имеет смысл? –

+1

Метод в классе реализации ДОЛЖЕН реализовать метод 'add()' из I1 ** и ** метод 'add()' из I2. Он реализует оба сразу. Приказ отсутствует. Как только ваш класс скажет, что он реализует I1 и I2, либо он фактически реализует оба, либо вы получаете ошибку компиляции. –

+0

+1 для отличного объяснения. – NeverGiveUp161

1

Что касается переопределения, считаются только типы параметров методов (8.4.2); возвращаемые типы и типы броска проверяются позже на отдельном этапе (8.4.8.3).

Класс может наследовать несколько методов с эквивалентными сигнатурами. (8.4.8.4) Там нет проблем. В вашем случае два метода наследуются, то оба они переопределяются одним методом.

My IDE IntelliJ правильно сообщает, что метод переопределяет два метода в двух супер интерфейсах.

В Java 7 и ранее проблема с алмазом отсутствует. Однако, поскольку Java 8, методы интерфейса могут иметь реализации! Поэтому проблема с алмазом может возникнуть, когда класс наследует два метода из двух интерфейсов. Javac может отклонить код, если такая двусмысленность существует. (Есть способы устранить неоднозначность).

+0

Я думаю, что проблема с алмазом возникла бы только в том случае, если производному интерфейсу было разрешено объявить реализацию для одного из своих родительских элементов, и я не думал, что это будет разрешено. Это или проблема алмаза может произойти по-другому? – supercat

+0

интерфейс может иметь метод 'default', который переопределяет метод родителя. – ZhongYu

+0

Интересно. Я бы подумал, что основной пример использования для добавления методов по умолчанию в интерфейсе будет заключаться в том, чтобы добавлять новые методы к интерфейсу без нарушения существующих реализаций, и для случая использования требовалось бы только добавлять методы к родительскому. Однако я вижу проблему с этой функцией, и она выходит за рамки алмаза: поскольку (в отличие от VB.NET) Java не требует, чтобы те методы, в которых реализованы элементы интерфейса, были помечены каким-либо образом, любой интерфейс, который добавляет новый член, рискует столкновение с именами методов, используемыми любым классом, который его реализует. – supercat