Подтвердить что ты не робот

Дженерики в Scala: реализация интерфейса/признака дважды?

Учитывая общий интерфейс, например следующий

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

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

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

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

4b9b3361

Ответ 1

Нет. Смешивание в том же признаке возможно только в 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

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

Ответ 2

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

class C {
  object IInt extends I[Int] { ... }
  object IString extends I[String] { ... }
  ...
}