Trait强制执行子类型方法的impl

时间:2017-05-23 20:38:53

标签: scala

Scala是否可以为具有子类类型的子类强制实施类型特征? IE浏览器。我想定义一个特征,强制所有子类型只为具体的子类型实现Ordered。所以我想确保特征 ATrait 的每个实现 TraitImpl 实现 Ordered [TraitImpl] 。下面是一个非工作示例来说明我想要做的事情。

trait ATrait extends Ordered[_ <: ATrait] {
}

class TraitImpl extends ATrait {
    override def compare(that: TraitImpl): Int = ???
}

4 个答案:

答案 0 :(得分:2)

@Sheng是对的,F-bounded多态可能是要走的路,但提供的代码不完整,因为它允许以下内容。

trait ATrait[T <: ATrait[T]] extends Ordered[T]

class B extends ATrait[B] {
  override def compare(that: B): Int = ???
}
class C extends ATrait[B] {
  override def compare(that: B): Int = ???
}

BC的出血并不是您想要的。更完整的实施就是这样。

trait ATrait[T <: ATrait[T]] {
  self: T with Ordered[T] =>
}

class B extends ATrait[B] with Ordered[B] {
  override def compare(that: B): Int = ???
}
class C extends ATrait[C] with Ordered[C] {
  override def compare(that: C): Int = ???
}

使用此功能,您无法在Ordered[B]的定义中使用C

<强>更新

或者,正如@Sheng所指出的那样,稍微简洁一点。

trait ATrait[T <: ATrait[T]] extends Ordered[T] {self: T =>}

class B extends ATrait[B] {
  def compare(that: B): Int = ???
}
class C extends ATrait[C] {
  def compare(that: C): Int = ???
}

答案 1 :(得分:0)

您可以创建F-bounded类型:

trait ATrait[T <: ATrait[T]] extends Ordered[T] {
}

class TraitImpl extends ATrait[TraitImpl] {
    override def compare(that: TraitImpl): Int = ???
}

更新:正如@jwvh所指出的,由于B是ATrait的另一个子类,因此class TraitImpl extends ATrait[B]也会编译,这不是不可破解的。请参考他的anwser以获得更完整的解决方案。

答案 2 :(得分:0)

我认为最优雅的解决方案是使用自我注释:

trait ATtrait[T] { self: Ordered[T] =>
}

实现此特征的每个类都必须实现有序,并且您可以在ATrait中使用有序方法。

答案 3 :(得分:0)

我认为,如果你“走出困境”,你可以通过上下文绑定更好。幸运的是,Scala为您提供了两种实现顺序,第二种是通过暗示。

trait A extends Ordered[T <: A[T]] {
  def compare(that: T)(implicit ordering: Ordering[T]): Int = {
    ordering.compare(this, that)
  }
}

class TraitImpl extends A[TraitImpl]

现在,您可以在呼叫网站上插入Ordering,无论您最终调用compare哪个地方都需要隐含,都可以避免以任何形式不断覆盖事物。

您可以使用某种package object控制默认订购导入,这样您就可以为用户或同事提供更好的导入体验。