除了继承方面,以下类模板之间也有区别:

1| trait TraitA extends TraitB

2| trait TraitA { self: TraitB => }


我想在TraitATraitB之间划分职责,但是如果没有后者,前者将无法运行。

您将如何表达这一意图?对我来说,解决方案[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,这是一个令人讨厌的可选限制。

10-05 21:42