2010-02-14 3 views
9

Вот пример использования нескольких наследований интерфейсов в Java, и есть проблема.Java: как вы называете эту множественную двусмысленность наследования?

Обратите внимание, что я полностью знаю, почему возникает проблема, и это не вопрос моего вопроса. Вопрос в том, как вы назовете эту конкретную неоднозначность наследования интерфейса, если есть имя для нее.

Например, в C++, неоднозначность, которая возникает при использовании множественного наследования реализации и не может определить, какой метод замещения использовать называется «алмазной проблемы»:

http://en.wikipedia.org/wiki/Diamond_problem

Теперь еще раз, я знайте, что здесь нет той же проблемы: это не главное. Дело в том, что имя было придумано в предыдущем случае.

И я хотел бы знать, существует ли имя для проблемы, которую я собираюсь описать.

Вот пример другого рода множественного наследования, где один интерфейс наследуется от двух других интерфейсов, которые имеют несовместимый тип метод возврата:

interface A { 
    void a(); 
    Integer c(); 
} 

interface B { 
    void b(); 
    Long c(); 
} 

interface MI extends A, B {...} 

(уведомление множественного наследования интерфейса при работе с использованием «расширяет» ключевое слово)

Вы не можете сделать это, потому что:

типа а и в несовместимы; как определяют с(), но с обратным несвязанный типа

имеет имя было придумано для описания этой ситуации?

+0

Что делать, если они имеют одно и то же имя, типы аргументов, типы возврата, но отличаются несовместимой семантикой? Будет ли этот случай включен в ваш вопрос или нет? – curiousguy

ответ

3

Я не уверен, что для этого есть определенное имя, или, по крайней мере, оно не очень часто используется. Это «просто» проблема неявного сопоставления методов интерфейса методам класса; если у вас могут быть перегрузки, которые различаются только по типам возвратов, тоже не было бы проблем. Таким образом, это сводится к проблеме сопоставления подписи/перегрузки/неявного метода.

В онлайн-книге «Мышление в Java» для нее нет имени. http://www.linuxtopia.org/online_books/programming_books/thinking_in_java/TIJ310_001.htm

Только боковое примечание, C# допускает явные реализации интерфейса, который решает эту проблему.

+0

Не задано ли задание так же, как ситуация для I4 в разделе «Сопоставление имен при объединении интерфейсов» из вашей ссылки? Поэтому я предполагаю, что это называется «коллизии имен при объединении интерфейсов». Я не понимаю? – MatrixFrog

+2

@MatrixFrog: Да, но «коллизии имен при объединении интерфейсов» звучат скорее как описание проблемы для меня, а не как «стандартное» имя проблемы. – Lucero

-2

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

Я пропустил точку или вы говорите о переменной «c»?

+0

Да. вы пропустили это. снова прочитайте вопрос. – shoosh

+0

... и 'c' не является переменной, даже полем ... это метод. – Lucero

+0

@zinc: «нет двусмысленности»? В примере кода из вопроса есть двусмысленность: Какова должна быть реализация MI.c() '? Целое или длинное? –

1

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

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

+0

Я не согласен: Java имеет несколько наследования интерфейсов, и я неоднократно заявлял в своем вопросе, что речь идет о множественном наследовании интерфейсов. И тогда специально используются ключевые слова «extends». Затем довольно многие считают, что наследование нескольких интерфейсов является множественным наследованием, потому что реализация в конце концов - это всего лишь деталь (реализация не существует на уровне OOA/OOD, это действительно просто детали ООП). Интерфейс C, несомненно, наследует абстракции, определенные A и B, и как переводчик OOD в OOP, все, что мне волнует, - это абстракции, а не детали реализации. – SyntaxT3rr0r

+0

@Tom: тогда вы можете обратиться к своему второму пункту: это сложнее, чем просто попытаться предоставить два противоречивых метода в одном классе или интерфейсе. Пример здесь - единственный случай, когда вы наследуете интерфейс (обратите внимание на ключевое слово «extends» еще раз) * из двух абстракций *, которые не будут работать. Во всех остальных случаях вы всегда можете использовать наследование нескольких интерфейсов в Java. – SyntaxT3rr0r

+0

Я не согласен с какой-либо вашей конкретной точкой, и я хорошо осведомлен о возможностях расширения нескольких интерфейсов Java. Я просто указывал, что «так вы смотрите на это». Я знаю, что существуют различия на объектно-ориентированном уровне проектирования. Тем не менее, когда вы справляетесь с этим, как (помимо семантики и того факта, что класс может реализовать суперинтерфейсы без реализации подинтерфейсов) является интерфейсом, расширяющим другой, отличный от предоставления всех определенных методов в одном интерфейсе? – Tom

2

Я также не знаю какого-либо конкретного имени для этой проблемы. Всякий раз, когда он возникал, он описывался в предложении, содержащем слова несовместимость возвращаемого типа в какой-то момент. Вы также можете назвать это Map/Set incompatibilty, так как это один из наиболее выдающихся и раздражающих примеров в библиотеках классов Java. Это делает невозможным использование одного и того же класса Map, а также Set или Collection только потому, что Map определяет метод remove (Object) с другим типом возврата, чем Collection.

public interface Collection<E> extends Iterable<E> { 
    boolean remove(Object o); 
} 
public interface Set<E> extends Collection<E> { 
} 
public interface Map<K,V> { 
    V remove(Object key); 
} 
0

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

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

Схема, реализованная в .NET, прекрасно работает там. К сожалению, в Java нет никакого способа сделать что-либо подобное. Я не знаю, что Java будет кричать, если интерфейс наследует другие интерфейсы с конфликтующими членами, но независимо от того, сквозит ли он в этот момент, не будет никакого способа создать класс, который мог бы его реализовать.