使用抽象类而不是trait的优势是什么(除了性能)?在大多数情况下,抽象类似乎可以被特征所取代。
当前回答
除了不能直接扩展多个抽象类,但可以将多个trait混合到一个类中之外,值得一提的是,trait是可堆叠的,因为trait中的超级调用是动态绑定的(它引用的是在当前类或trait之前混合的类或trait)。
摘自Thomas在《抽象阶级与特质的区别》中的回答:
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
其他回答
我能想到两个不同点
抽象类可以有构造函数形参和类型形参。trait只能有类型参数。有一些讨论说,将来甚至trait也可以有构造函数形参 抽象类与Java完全可互操作。您可以从Java代码中调用它们,而不需要任何包装器。trait只有在不包含任何实现代码的情况下才完全可互操作
抽象类可以包含行为——它们可以用构造函数参数化(trait不能)并表示一个工作实体。trait只是代表一个单一的特性,一个功能的界面。
无论如何,Odersky等人在《Scala编程》一书中建议,当你怀疑时,就使用trait。如果需要,您可以随时将它们更改为抽象类。
在Programming Scala中,作者说抽象类构成了典型的面向对象的“is-a”关系,而特征则是一种Scala组合方式。
当扩展一个抽象类时,这表明子类是类似的。我认为在使用特质时并不一定是这样。
推荐文章
- Scala 2.8 breakOut
- 如何克隆一个案例类实例,只改变一个字段在Scala?
- ':_* '(冒号下划线*)在Scala中有什么作用?
- 定义一个函数时,“def”和“val”有什么区别
- 在Scala中获取列表中的项目?
- case对象和对象的区别
- Scala中的Case对象与枚举
- 任务不可序列化:java.io.NotSerializableException,当只对类而不是对象调用闭包外部的函数时
- 在Scala中将一个元素附加到列表的末尾
- 在Scala中按名称调用vs按值调用,需要澄清
- 解析命令行参数的最佳方法?
- Android Scala编程
- lazy val做什么?
- Scala:抽象类型vs泛型
- 如何在准引用中使用无形?