Абстрактные классы / черты и инвариантные функции - PullRequest
2 голосов
/ 14 декабря 2010

С учетом признака T

trait T {
  def v: Int
  def +(t: T): T
}

следующий класс A

case class A(v: Int) extends T {
  def +(a: A) = A(v + a.v)
}

не является допустимым подтипом T.Реализация A.+ является слишком строгой, поскольку она принимает только элементы типа A, тогда как подпись T.+ требует, чтобы все реализации могли принимать объекты типа T, а не только объекты типа A,Пока что разумно.

Если бы я хотел, чтобы реализации T были такими ограничительными, я мог бы изменить объявления T и A следующим образом

trait T[This <: T[This]] {
  def v: Int
  def +(t: This): This
}

case class A(v: Int) extends T[A] {
  def +(a: A) = A(v + a.v)
}

, который явно взрывает сигнатуру типа.

Есть ли другой способ объявить, что реализации T должны быть совместимы только с объектами своего типа?

1stРЕДАКТИРОВАТЬ В ответ на Ответ Landei ниже :

Хотя самопечатания действительно сокращают текущую подпись, они не сокращают другие подписи, где встречается T, например

trait C[D <: T[D], S] { self: S =>
  def +(perm: D): S
  def matches(other: S): Boolean
}

Ответы [ 2 ]

1 голос
/ 16 декабря 2010

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

trait TT {
  type This <: TT
  def v: Int
  def +(t: This): This
}
case class AA(v: Int) extends TT {
  type This = AA
  def +(a: This) = AA(v + a.v)
}
1 голос
/ 14 декабря 2010

Вы можете использовать собственные типы:

trait T[S] {
  self:S => 
  def v: Int
  def +(t: S): S
}

case class A(v: Int) extends T[A] {
  def +(a: A) = A(v + a.v)
}
...