Может быть реализована только одна параметризация интерфейса - как обойти это? - PullRequest
1 голос
/ 02 августа 2009

Вот пример того, что я хотел бы сделать (на Java):

interface MyInterface<E> {
  public void doSomething(E foo);
}

class MyClass implements MyInterface<ClassA>, MyInterface<ClassB> {
  public void doSomething(ClassA fooA) {
    ...
  }

  public void doSomething(ClassB fooB) {
    ...
  }
}

Когда я пытаюсь реализовать это, компилятор говорит мне, что я могу реализовать MyInterface только один раз в MyClass. Я предполагал, что MyInterface<ClassA> рассматривается как другой тип по сравнению с MyInterface<ClassB>, но, очевидно, нет Это кажется чем-то очень полезным, поэтому я удивлен ошибкой.

Обновление: спасибо за помощь. Как указано в одном из комментариев, вышеизложенное является абстрактным; проблема, которую я пытаюсь решить, состоит в том, чтобы реализовать шаблон Observer таким образом, чтобы класс-наблюдатель объявлял те классы, которые он наблюдает, через интерфейсы, которые он реализует, а также имеет дело с изменениями объектов, которые он наблюдает в специфичных для класса методах. Преимущество использования такого подхода состоит в том, что из интерфейсов ясно, какой класс реализует, какой тип объектов он наблюдает, и поэтому компилятор заставляет программиста явно реализовывать обработку изменений в экземплярах тех классов, которые наблюдаются. Таким образом, приведенный выше абстрактный код может выглядеть примерно так:

interface IsObserverOf<E> {
  public void observedDidChange(E foo);
}

class MyClass implements IsObserverOf<Database>, IsObserverOf<Spreadsheet> {
  public void observedDidChange(Database database) {
    ...
  }

  public void observedDidChange(Spreadsheet spreadsheet) {
    ...
  }
}

Здесь MyClass заявляет, что он наблюдает за объектами базы данных и объектами электронных таблиц, и компилятор будет - в идеальном мире - требовать реализации двух разных методов наблюдаемыхDidChange ().

Спасибо.

Ответы [ 2 ]

5 голосов
/ 02 августа 2009

Возможно, вы ищете Шаблон посетителя (он же "двойная отправка").

5 голосов
/ 02 августа 2009

Из-за типа Erasure , параметры универсального бита интерфейса исчезают при компиляции и запуске. Что касается Java, то MyInterface<ClassA> и MyInterface<ClassB> идентичны и становятся просто MyInterface при компиляции. Я полагаю, когда они реализовали обобщенные элементы, можно было бы обработать нужный вам случай (разные типы для параметров метода), но как бы Java обрабатывал метод, в котором универсальный параметр используется для возвращаемого типа:

interface Foo<T> {
    T getSomeObject();
}

Проблема в том, что вы не можете перегрузить метод, единственное отличие которого - тип возвращаемого значения, поэтому это серьезно ограничило бы полезность возможности делать что-то вроде implements MyInterface<ClassA|ClassB>.

...