除了继承方面之外,下面这些类模板有什么区别:
1| trait TraitA extends TraitB
2| trait TraitA { self: TraitB => }
我希望将职责分配给 TraitA
和 TraitB
,但前者没有后者无法正常运行。
您如何表达这个意图? 对我来说,解决方案[2]可能是比较自然的方法。但我不想让实现者混合需要混入的东西,从而增加负担。
除了继承方面之外,下面这些类模板有什么区别:
1| trait TraitA extends TraitB
2| trait TraitA { self: TraitB => }
我希望将职责分配给 TraitA
和 TraitB
,但前者没有后者无法正常运行。
您如何表达这个意图? 对我来说,解决方案[2]可能是比较自然的方法。但我不想让实现者混合需要混入的东西,从而增加负担。
通常我更偏好使用[1],因为正如您所说,实现者不需要混合(子类型)TraitB
。也许如果出于某种原因希望不继承TraitB
中的具体实现并迫使实现者在TraitB
的子类型中进行选择,则更倾向于[2]。尽管如此,[1]同样具有灵活性。
我只在必要时使用[2],例如当类型不是已知类或特征时,
// Here, Matrix cannot extend type parameter Repr
trait Matrix[+Repr <: Matrix[Repr]] { self: Repr =>
...
}
更新。 这里还有一个小差别,
trait B
trait A { self: B => }
def g(ab: A): B = ab // Type mismatch: found A, required B
尽管类型已被合并,但无法将A
用作B
,这是一种可选的限制,有些让人烦恼。
A
“与之合作”,但同时“不是”一个B
的关系。对我来说,这有点像私有继承和公共继承。 - Tim Friske