Scala中抽象trait的语义学

16

我想知道在使用 trait 时结合 abstract 关键字的语义。

如果 trait 没有定义任何抽象方法,那么使用 abstract 关键字并不会阻止我创建一个实例:

scala> abstract trait T
defined trait T

scala> new T{}
res0: java.lang.Object with T = $anon$1@12cd927d

另一方面,如果特征定义了一个抽象方法,无论是否存在abstract关键字,我都不能创建实例(当然,必须实现此方法):

scala> abstract trait T { def foo : Unit }
defined trait T

scala> new T{}
<console>:9: error: object creation impossible, since method foo in trait T of type =>    Unit is not defined
              new T{}
                  ^

scala> trait T { def foo : Unit }
defined trait T

scala> new T{}
<console>:9: error: object creation impossible, since method foo in trait T of type =>     Unit is not defined
              new T{}
                  ^

那么,在一个 trait 前面加上 abstract 关键字有什么好处呢?


2
你不能创建一个特质的实例。当你使用 new T{} 时,你创建了一个匿名对象,它混入了特质 T。 - kiritsuku
2个回答

31

2

您并不是在创建一个特质的实例。特质无法被实例化。

您正在创建一个扩展该特质的匿名类的实例。

一般来说,

new __t__

等同于

{ class __anonymous__ extends __t__; new __anonymous__ }

(其中__anonymous__是匿名类的新鲜名称,对用户程序不可访问。)

这在Scala语言规范的第6.10节:实例创建表达式中有详细说明。

因此,在第一个示例中创建实例的原因是因为您没有创建特质(抽象的),而是对象(非抽象的)。

在第二个示例中,不能创建实例的原因是,如果您从某个东西(无论是特质还是类)继承,那么您最终必须在继承链的某个位置实现其抽象方法以实例化它。在第一个示例中,没有需要实现的抽象方法。

abstract关键字本身并没有任何区别:trait是隐式抽象的,该关键字是多余的。


4
我认为你的意思是他正在创建一个匿名,并将trait作为mixin混入其中。 - oxbow_lakes
抱歉,是的。它是一个匿名类的实例,该类是 trait 的子类。呼。 - Jörg W Mittag

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接