Scala 为什么父列表中的第一个基类必须是非特征类?
在中,据说在类模板中,Scala 为什么父列表中的第一个基类必须是非特征类?,scala,inheritance,traits,Scala,Inheritance,Traits,在中,据说在类模板中,sc扩展了mt1,mt2,…,mtn 每个特征参考mti必须表示一个特征。相比之下 超类构造函数sc通常指的是一个不是 特质可以写一个以字母开头的家长列表 特征参考,例如mt1和……和mtn。在这种情况下 父项列表被隐式扩展以包括父项的超类型 mt1作为第一个父类型。新的超类型必须至少有一个 不接受参数的构造函数。在下文中,我们将 始终假定已执行此隐式扩展,以便 模板的第一个父类是常规超类 构造函数,而不是特征引用 如果我理解正确,我认为这意味着: trait Base1
sc扩展了mt1,mt2,…,mtn
每个特征参考mti必须表示一个特征。相比之下
超类构造函数sc通常指的是一个不是
特质可以写一个以字母开头的家长列表
特征参考,例如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 {}
我的问题是:
类子扩展Mt1、Mt2
)或特征模板(例如特征子扩展Mt1、Mt2
)Java.lang.Object
(Scala中的AnyRef
)。因此,由于您正在定义一个具体的类,因此您将隐式地继承对象
。如果您与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不能有构造函数参数。此外,没有构造函数参数传递给trait的超类。这是不必要的,因为特征是在超类初始化之后初始化的
假设特征D定义了C类型实例x的某些方面(即D是C的基类)。那么x中D的实际超类型是由L(C)中继承D的所有基类组成的复合类型
这是定义没有参数的基本构造函数所必需的
3) 根据答案(2),需要定义基本构造函数(1)基本上是的,您的理解是正确的。与Java中一样,每个类都继承自Java.lang.Object
(Scala中的AnyRef
)。因此,由于您正在定义一个具体的类,因此您将隐式地继承对象
。如果您与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不能有构造函数参数。此外,没有构造函数参数传递给trait的超类。这是不必要的,因为特征是在超类初始化之后初始化的
假设特征D定义了C类型实例x的某些方面(即D是C的基类)。那么x中D的实际超类型是由L(C)中继承D的所有基类组成的复合类型
这是定义没有参数的基本构造函数所必需的
3) 根据答案(2),需要定义基本构造函数免责声明:我不是,也从来不是“Scala设计委员会”或类似组织的成员,所以“为什么?”问题的答案主要是猜测,但我认为这是一个有用的答案 免责声明#2:我写这篇文章花了好几个小时,拍了好几次,所以可能不太一致 免责声明#3(对未来读者来说,这是一个可耻的自我推销):如果你觉得这个很长的答案很有用,你也可以看看黄立夫关于类似主题的另一个问题 简短回答 这是一个复杂的问题,我不认为有一个好的简短的答案,除非你已经知道答案是什么。虽然我的真实答案很长,但以下是我最好的简短答案: 为什么父列表中的第一个基类必须是非特征类 因为必须只有一个非特征基类,如果它总是第一个基类,那么事情就更容易了
类子扩展Mt1、Mt2
)或特征模板(例如特征子扩展Mt1、Mt2
)Mt1
有自己的“超类型”被提升到扩展它的类中呢
事实上,这里有两个不明显的例子证明了这一点:
示例#1
这个例子失败了,因为规范说
extends子句用mt1mt1扩展scsc,用mtnmtn扩展scsc
可以省略,在这种情况下扩展scala。假定为AnyRef
因此TNo
实际上扩展了与AnyVal
不兼容的AnyRef
示例2
再次ChildBad
失败,因为TSecond
需要cssecond
但TFirst
仅提供CFirst
作为基类
class CFirst
class CSecond extends CFirst
// did you know that traits can extend classes as well?
trait TFirst extends CFirst
trait TSecond extends CSecond
// works
class ChildGood extends TSecond with TFirst
// fails
// illegal inheritance; superclass CFirst is not a subclass of the superclass CSecond of the mixin trait TSecond
class ChildBad extends TFirst with TSecond
trait Achilles {
def getAchillesPos: Int
def stepAchilles(): Unit
}
class AchillesImpl(var achillesPos: Int) extends Achilles {
def getAchillesPos: Int = achillesPos
def stepAchilles(): Unit = {
achillesPos += 2
}
}
class TortoiseImpl(var tortoisePos: Int) {
def getTortoisePos: Int = tortoisePos
def stepTortoise(): Unit = {
tortoisePos += 1
}
}
class AchillesAndTortoise(handicap: Int) extends AchillesImpl(0) with TortoiseImpl(handicap) {
def catchTortoise(): Int = {
var time = 0
while (getAchillesPos < getTortoisePos) {
time += 1
stepAchilles()
stepTortoise()
}
time
}
}
class CBase {
def getValue = 2
}
trait TFirst extends CBase {
override def getValue = super.getValue + 1
}
trait TSecond extends CFirst {
override def getValue = super.getValue * 2
}
class CThird extends CBase with TSecond {
override def getValue = 100 - super.getValue
}
class Child extends TFirst with TSecond with CThird
trait TFourth extends CThird
class AnotherChild extends TFirst with TSecond with TFourth