使用抽象类而不是特质的优点是什么?
使用抽象类代替性状(除了表现)的优点是什么?在大多数情况下,似乎可以将抽象类替换为特征。
What is the advantage of using an abstract class instead of a trait (apart from performance)? It seems like abstract classes can be replaced by traits in most cases.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(8)
我可以想到两个差异
I can think of two differences
在Scala中有一个章节,称为“特征,还是特征?” 解决这个问题。由于第一版可以在线提供,因此我希望可以在这里引用整个内容。 (任何严重的Scala程序员都应购买这本书):
正如@mushtaq Ahmed所提到的那样,特征不能将任何参数传递给类的主要构造函数。
另一个区别是
super
的处理。请参阅其余的第12章,有关更多详细信息。
编辑1(2013):
与特征相比,抽象类的行为方式存在细微的差异。线性化规则之一是它保留了类的继承层次结构,该类别倾向于在链条后期推动抽象类,而特征可以愉快地混合在一起。在某些情况下,实际上最好是在类线性化的后面位置。 ,因此可以将抽象类用于此。参见 scala 中的class linearization(mixin Order)。
编辑2(2018):
从Scala 2.12开始,特质的二进制兼容性行为已经改变。在2.12之前,将成员添加或删除成员在特征中需要重新编译所有继承特征的类,即使这些类未更改。这是由于特征在JVM中编码的方式。
从Scala 2.12开始,特征,因此要求放松了一下。如果特征执行以下任何内容,则其子类仍需要重新编译:
,但是如果特征没有,您现在可以在不破坏二进制兼容性的情况下进行更新。
There's a section in Programming in Scala called "To trait, or not to trait?" which addresses this question. Since the 1st ed is available online, I'm hoping it's OK to quote the whole thing here. (Any serious Scala programmer should buy the book):
As @Mushtaq Ahmed mentioned, a trait cannot have any parameters passed to the primary constructor of a class.
Another difference is the treatment of
super
.See the rest of Chapter 12 for more details.
Edit 1 (2013):
There is a subtle difference in the way abstract classes behaves compared to traits. One of the linearization rules is that it preserves the inheritance hierarchy of the classes, which tends to push abstract classes later in the chain while traits can happily be mixed in. In certain circumstances, it's actually preferable to be in latter position of the class linearization, so abstract classes could be used for that. See constraining class linearization (mixin order) in Scala.
Edit 2 (2018):
As of Scala 2.12, trait's binary compatibility behavior has changed. Prior to 2.12, adding or removing a member to the trait required recompilation of all classes that inherit the trait, even if the classes have not changed. This is due to the way traits were encoded in JVM.
As of Scala 2.12, traits compile to Java interfaces, so the requirement has relaxed a bit. If the trait does any of the following, its subclasses still require recompilation:
But if the trait does not, you can now update it without breaking binary compatibility.
无论值得什么值,Odersky等人的
For whatever it is worth, Odersky et al's Programming in Scala recommends that, when you doubt, you use traits. You can always change them into abstract classes later on if needed.
除了您不能直接扩展多个抽象类的事实,但是您可以将多个特征混合到一个类中,还值得一提的是特征是可堆叠的,因为特征中的超级呼叫是动态绑定的(它是在以前混合的类或特征当前一个)。
从中的差异之间的差异:
Other than the fact that you cannot directly extend multiple abstract classes, but you can mixin multiple traits into a class, it's worth mentioning that traits are stackable, since super calls in a trait are dynamically bound (it is referring a class or trait mixed before current one).
From Thomas's answer in Difference between Abstract Class and Trait:
在扩展抽象类时,这表明子类是类似的。我认为,在使用特征时,情况并非如此。
When extending an abstract class, this shows that the subclass is of a similar kind. This is not neccessarily the case when using traits, I think.
在
In Programming Scala the authors say that abstract classes make a classical object oriented "is-a" relationship while traits are a scala-way of composition.
抽象类可以包含行为 - 它们可以用构造函数args(特征不能)参数化并代表一个工作实体。特征相反,只表示一个功能的一个功能。
Abstract classes can contain behaviour - They can parameterized with constructor args (which traits can't) and represent a working entity. Traits instead just represent a single feature, an interface of one functionality.