Композиция с той же чертой, но с разными параметрами типа - PullRequest
8 голосов
/ 14 августа 2011

В настоящее время мне интересно составить объект / класс / черту, которая соответствует одной черте для параметров нескольких типов. Допустим, у меня есть

trait Dependent[T]{
  def observeCritereaChanged(oldValue:T, newValue:T):Unit
}

Я бы хотел иметь возможность определить некоторую черту, которая реализует зависимость для двух разных типов параметров, например

trait IntStrDependent extends Dependent[Int] with Dependent[String]

Так что экземпляры моей черты IntStrDependent должны были бы определить observeCritereaChanged для обоих типов:

class MyDependent extends IntStrDependent {
  def observeCritereaChanged(oldValue:Int, newValue:Int) = //...
  def observeCritereaChanged(oldValue:String, newValue:String) = //...
}

Пока что мои попытки встретились с ошибкой компиляции при попытке создать черту IntStrDependent:

scala> trait IntStrDependent extends Dependent[Int] with Dependent[String]
<console>:8: error: illegal inheritance;
 self-type IntStrDependent does not conform to Dependent[Int]'s selftype Dependent[Int]
       trait IntStrDependent extends Dependent[Int] with Dependent[String]
                                     ^
<console>:8: error: illegal inheritance;
 self-type IntStrDependent does not conform to Dependent[String]'s selftype Dependent[String]
       trait IntStrDependent extends Dependent[Int] with Dependent[String]
                                                         ^

Итак, мой вопрос: есть ли способ сделать то, что я пытаюсь сделать (если да, то как), или это безнадежное дело, потому что Scala не создан для таких вещей?

1 Ответ

3 голосов
/ 14 августа 2011

Хороший вопрос. Я не думаю, что вы можете делать то, что вы хотите напрямую.

Один альтернативный подход - trait IntStrDependent extends Dependent[Either[Int, String]], но это не совсем решает проблему. Возможно, вариант кодирования типа 1004 * объединения Майлза Сабина позволяет сделать что-то более причудливое.

Я думаю, что лучший вариант - это просто,

trait Dependent[T]{
  def observeCritereaChanged(oldValue:T, newValue:T):Unit
}

trait IntStrDependent {
  val I: Dependent[Int]
  val S: Dependent[String]
}

object MyDependent extends IntStrDependent {
  object I extends Dependent[Int] {
    def observeCritereaChanged(oldValue:Int, newValue:Int) {}
  }
  object S extends Dependent[String] {
    def observeCritereaChanged(oldValue:String, newValue:String) {}
  }
}

Чтобы использовать MyDependent, необходимо явно выбрать вариант Int или String, как в

MyDependent.I.observeCritereaChanged(1, 2)

По моему мнению, делать явную зависимость типа в любом случае - хорошая вещь.

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