Scala是否可以为具有子类类型的子类强制实施类型特征? IE浏览器。我想定义一个特征,强制所有子类型只为具体的子类型实现Ordered。所以我想确保特征 ATrait 的每个实现 TraitImpl 实现 Ordered [TraitImpl] 。下面是一个非工作示例来说明我想要做的事情。
trait ATrait extends Ordered[_ <: ATrait] {
}
class TraitImpl extends ATrait {
override def compare(that: TraitImpl): Int = ???
}
答案 0 :(得分:2)
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 = ???
}
B
向C
的出血并不是您想要的。更完整的实施就是这样。
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
控制默认订购导入,这样您就可以为用户或同事提供更好的导入体验。