为什么可以在 Scala 中实例化多个特征,而不是单个特征?

Why is it possible to instantiate multiple traits in Scala, but not a single one?

假设我们有两个特征:

trait Trait1
trait Trait2

如果我尝试类似 val single = new Trait1 的操作,我会得到一个错误 error: trait Trait1 is abstract; cannot be instantiated。但是,val twoTraits = new Trait1 with Trait2 编译。为什么会这样?

P.S。我还观察到 val single = new Trait1 {} 编译得很好。你能提供一个适当的解释吗?

从技术上讲,您不能直接实例化单个特征或多个混合特征,但编译器使用一些语法糖可以让您创建 anonymous classes扩展它们。假设我们有:

trait A
trait B

当您调用 new A with B 时,真正发生的是编译器正在创建一个混合了 AB 的匿名 class。你得到:

final class $anon extends A with B
new $anon()

当您调用 new A {} 时,同样的事情也会发生。你得到一个扩展 A:

的匿名 class
final class $anon extends A
new $anon()

唯一的区别是语法上的。从单个特征创建匿名 class 时,您至少需要使用大括号 {} 将其与 class 区分开来。也就是说,更容易辨别模板是否可以构造,或者必须包裹在一个匿名的class中才能构造。对于多个特征(甚至 class 混合特征),编译器理解它将 总是 需要首先创建一个匿名 class。

总结一下:

class C

new A {}       // Anonymous class that extends A, then constructed
new A with B   // Anonymous class that extends A with B, then constructed
new C          // Constructed instance of class C
new C with A   // Anonymous class that extends C with A, then constructed