为什么父列表中的第一个基类必须是非特征类?

时间:2018-01-02 17:44:48

标签: scala inheritance traits

Scala spec中,据说在课程模板sc extends mt1, mt2, ..., mtn

  

每个特征参考mti必须表示特征。相比之下,   超类构造函数sc通常是指一个不是a的类   特征。可以编写以a开头的父母列表   特征参考,例如mt1与......与mtn。在那种情况下   父母列表被隐式扩展为包括超类型   mt1作为第一个父类型。新的超类型必须至少有一个   不带参数的构造函数。在下面,我们将   总是假设已经执行了这个隐式扩展,所以   模板的第一个父类是常规超类   构造函数,而不是特征参考。

如果我理解正确,我认为这意味着:

trait Base1 {}
trait Base2 {}
class Sub extends Base1 with Base2 {}

将隐式扩展为:

trait Base1 {}
trait Base2 {}
class Sub extends Object with Base1 with Base2 {}

我的问题是:

  1. 我的理解是否正确?
  2. 此要求(父列表中的第一个子类必须是非特征类)和隐式扩展仅适用于类模板(例如class Sub extends Mt1, Mt2)或特征模板(例如trait Sub extends Mt1, Mt2) ?
  3. 为什么需要这个要求和隐式扩展?

1 个答案:

答案 0 :(得分:1)

1)基本上是的,你的理解是正确的。与Java类似,每个类都继承自java.lang.Object(Scala中的AnyRef)。因此,既然您要定义一个具体的类,那么您将隐式继承自Object。如果你用REPL检查,你得到:

scala> trait Base1 {}
defined trait Base1

scala> trait Base2 {}
defined trait Base2

scala> class Sub extends Base1 with Base2 {}
defined class Sub

scala> classOf[Sub].getSuperclass
res0: Class[_ >: Sub] = class java.lang.Object

2)是的,来自" Traits"规范中的段落,这也适用于他们。在"模板"我们有一段:

  

新的超类型必须至少有一个不带参数的构造函数

然后在" Traits"段:

  

与普通类不同,traits不能有构造函数参数。此外,没有构造函数参数传递给特征的超类。这是没有必要的,因为在初始化超类之后初始化了traits。

     

假设特征D定义了类型C的实例x的某些方面(即D是C的基类)。然后,x中D的实际超类型是由L(C)中所有成功D的基类组成的复合类型。

这是定义没有参数的基础构造函数所必需的。

3)根据答案(2),需要定义基础构造函数