假设我们有两个特征:
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 {}
编译的很好。您能提供适当的解释吗?
从技术上讲,您无法直接实例化单个特征或多个混合特征,但是编译器使用一些句法糖,使您可以创建扩展的匿名类他们。假设我们有:
trait A
trait B
当您调用new A with B
时,真正发生的是编译器正在创建一个匿名类,该类同时混合了A
和B
。你得到:
final class $anon extends A with B
new $anon()
当您致电new A {}
时,也会发生同样的事情。您将获得一个扩展A
的匿名类:
final class $anon extends A
new $anon()
唯一的区别是句法。从单个特征创建匿名类时,您至少需要使用括号{}
将其与类区分开。也就是说,更容易辨别模板是否可以构造,或者必须包裹在匿名类中才能构造。具有多个特征(甚至具有混合特征的类别),编译器知道它将始终首先创建一个匿名类。
总结:
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