抽象类和特征之间的区别[重复]
Posted
技术标签:
【中文标题】抽象类和特征之间的区别[重复]【英文标题】:Difference between Abstract Class and Trait [duplicate] 【发布时间】:2011-01-01 14:49:41 【问题描述】:可能重复:Scala traits vs abstract classes
抽象类和特征之间的概念区别是什么?
【问题讨论】:
你看到***.com/questions/1991042/…了吗?在那个 SO 问题中有一些回应元素。 【参考方案1】:一个类只能extend one superclass,因此只有一个抽象类。如果你想组合几个类,Scala 的方法是使用mixin class composition:你结合一个(可选的)超类、你自己的成员定义和一个或多个traits。与类相比,特征受到限制,因为它不能具有构造函数参数(比较 scala reference manual)。
引入了特性与类相比的限制,以避免多重继承的典型问题。关于继承层次结构或多或少有一些复杂的规则;最好避免真正重要的层次结构。 ;-) 据我了解,只有从两个不同的特征继承具有相同签名的两个方法/具有相同名称的两个变量才有意义。
【讨论】:
只要你的层次结构是一棵树,你就不会遇到复杂的场景。 @edit:如果超类型没有继承相同的特征,您可能会发生冲突。任何两个具有相同名称和参数(类型)列表的方法冲突。 @Raphael 好点。我试图澄清这一点。现在正确吗? 我想是的。值得注意的是,Scala 以明确定义的方式解决了此类冲突(“后来的”特征具有偏好)。目前,我不明白为什么同样的技术不能解决类的多重继承,所以我不知道特质的限制是否真的是因为这个。 @andershqst 您可以滥用某些东西只是根本不使用某些东西的弱理由。如果你想从 java 代码中调用某些东西,让它(例如 trait)实现一个 java 接口通常是一个好主意。 trait 相对于接口的一个优点是您可以在以后扩展它而不会破坏其他代码。 (不过,您必须重新编译它。)我还看到了特征的不错用途,您可以通过仅包含特征来使用基本算法的变体。例如,在标准库中,“new TreeSet”为您提供了一个基本集,“带有 SynchronizedSet 的新 Treeset”是同步的。【参考方案2】:特征的一个方面是它们是可堆叠的。允许 AOP 的约束形式(围绕建议)。
trait A
def a = 1
trait X extends A
override def a =
println("X")
super.a
trait Y extends A
override def a =
println("Y")
super.a
scala> val xy = new AnyRef with X with Y
xy: java.lang.Object with X with Y = $anon$1@6e9b6a
scala> xy.a
Y
X
res0: Int = 1
scala> val yx = new AnyRef with Y with X
yx: java.lang.Object with Y with X = $anon$1@188c838
scala> yx.a
X
Y
res1: Int = 1
super
的分辨率反映了继承层次的线性化。
【讨论】:
cool ... 如果两个特征 X 和 Y 为 def a 产生不同的值怎么办? 对不起! @Thomas 制作可堆叠特征有一些规则,你做出错误的解释,不幸的是我支持你。【参考方案3】:从概念上讲,特征是类的组成部分,而不是类本身。因此,它通常没有构造函数,也不意味着“独立存在”。
我建议使用具有独立含义的抽象类,而当您只想以面向对象的方式添加功能时使用特征。 如果您不确定两者之间的关系,您可能会发现,如果您的所有方法都围绕着做一件事情,那么您可能需要一个 trait。
对于一个(非特定语言)示例,如果您的 Employee 应该同时扩展“Person”和“Cloneable”,请将 Person 设为基类,将 Cloneable 设为 trait。
【讨论】:
我想说,当所有的方法都围绕着做一件事情时,你的设计是可以的(单一责任原则:en.wikipedia.org/wiki/Single_responsibility_principle)。否则设计应该是一个可辩护的妥协。 你说得对,我把我的回答澄清了一点。【参考方案4】:至少在 Scala 中,特征系统有一种明确的方式在子类中声明父优先级,以避免与多重继承相关的典型问题,即与具有相同签名的继承方法冲突。
Traits 类似于 Java 接口,但允许具有方法实现。
【讨论】:
绑定优先级不是通过特征本身解决的,而是通过超类型列表的线性化来解决的。你可以通过多类继承来做同样的事情。以上是关于抽象类和特征之间的区别[重复]的主要内容,如果未能解决你的问题,请参考以下文章