抽象类/特征和不变函数

时间:2010-12-14 11:09:48

标签: generics inheritance scala signature variance

给出特征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的实施具有限制性,我可以修改TA的声明,如下所示

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的实现只需要与自己类型的对象兼容吗?

第一次编辑回复Landei's answer below

虽然自我类型确实缩短了当前的签名,但它们并没有缩短T出现的其他签名,例如。

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

2 个答案:

答案 0 :(得分:1)

您可以使用自我类型:

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)
}

答案 1 :(得分:1)

您可以使用类型成员执行此操作。我不知道你到底是什么品牌的“短”。有一些冗余,但另一方面,没有类型参数可以节省大量的支架。

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)
}