Дженерики в Scala: дважды реализовать интерфейс / черту? - PullRequest
12 голосов
/ 27 сентября 2011

С учетом универсального интерфейса, такого как следующий

interface I<T> {
    void m(T t);
}

Я могу в C # создать класс, который реализует I дважды (или более) с разными типами, предоставленными для T, например,

class C : I<int>, I<String> {
   public void m(int i) { }
   public void m(String s) { }
}

Это не может быть сделано в Java из-за удаления общей информации о типе, но может ли что-то подобное быть достигнуто в Scala?

Ответы [ 2 ]

12 голосов
/ 27 сентября 2011

Нет.Смешивание в одной и той же черте возможно только в Scala, если два типа, с которыми эта характеристика (интерфейс) параметризуется с типами, которые соответствуют друг другу, и эта черта не смешивается в одном классе дважды непосредственно .Чтобы убедиться, что эти 2 типа соответствуют друг другу, вам обычно нужно сделать параметр типа ковариантным (+).

Например, это недопустимо:

scala> trait A[+T] { def foo: T = sys.error() }
defined trait A

scala> class C extends A[AnyRef] with A[String]
<console>:8: error: trait A is inherited twice
       class C extends A[AnyRef] with A[String]

Но это:

scala> trait A[+T] { def foo: T = sys.error() }
defined trait A

scala> class C extends A[AnyRef]
defined class C

scala> class B extends C with A[String]
defined class B

Обратите внимание, что в этом случае вы не получите семантику с перегрузкой , как в случае с C #, но семантику с переопределением - всеметоды в A с соответствующей сигнатурой будут объединены в одном методе с наиболее конкретной сигнатурой, при этом метод выбирается в соответствии с правилами линеаризации вместо использования одного метода для каждого смешанного признакав.

10 голосов
/ 27 сентября 2011

Нет, не может. Обычно в этом случае я делаю

class C {
  object IInt extends I[Int] { ... }
  object IString extends I[String] { ... }
  ...
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...