除了继承方面,以下类模板之间也有区别:
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
,这是一个令人讨厌的可选限制。