抱歉,这个问题可能有点长,因为我想尽可能准确地描述问题和我的理解。
最近在学习Scala的trait系统。
我对冲突成员做了一些实验,见以下代码:
trait TA {
def play() = println("TA play")
}
trait TB {
def play() = println("TB play")
}
trait TC {
def play() = println("TC play")
}
class MyClass extends TA with TB with TC {
}
Run Code Online (Sandbox Code Playgroud)
当然,这段代码按照预期编译失败了:
Error:(13, 8) class MyClass inherits conflicting members:
method play in trait TB of type ()Unit and
method play in trait TC of type ()Unit
(Note: this can be resolved by declaring an override in class MyClass.)
class MyClass extends TA with TB with TC {
^
Run Code Online (Sandbox Code Playgroud)
我的理解是
class 的线性化为MyClass ,{MyClass, TC, TB, TA}但由于没有overrideof和of ,所以编译失败play。TBplayTC
一种解决方法是标记override、TA、TB,TC如下所示:
trait IPlay {
def play()
}
trait TA extends IPlay {
override def play() = println("TA play")
}
trait TB extends IPlay {
override def play() = println("TB play")
}
trait TC extends IPlay {
override def play() = println("TC play")
}
class MyClass extends TA with TB with TC {
}
Run Code Online (Sandbox Code Playgroud)
OK,这段代码果然可以编译成功了。
但是这个呢:
trait TA {
def play() = println("TA play")
}
trait TB {
def play() = println("TB play")
}
trait TC {
def play() = println("TC play")
}
class MyClass extends TA with TB with TC {
override def play(): Unit = {
println("MyClass play")
super.play()
super[TC].play()
super[TA].play()
super[TB].play()
}
}
(new MyClass).play()
// -- Output:
// MyClass play
// TC play
// TC play
// TA play
// TB play
Run Code Online (Sandbox Code Playgroud)
让我惊讶的是这段代码也能编译成功。
class 的线性化仍然MyClass是,{MyClass, TC, TB, TA}并且没有overrideon和the ,唯一的区别是我在 中添加了一个on 。playTBplayTCoverrideplayMyClass
为什么可以编译成功呢?
请注意,Scala 不是 Java 或 C#,不存在冲突成员的默认行为。
在 Java 中,如果不将方法标记为@Override,则默认行为是覆盖。
在 C# 中,如果不将方法标记为override,则默认行为是隐藏。
在 Scala 中,如果您不将方法标记为override,则没有默认行为,它们应该是冲突的成员,IMO。
因此,我认为上面的代码编译应该是失败的,但是为什么能够成功呢?
或者我的理解是错误的。
很感谢。
小智 1
您已在子类中手动定义行为。\n您为什么感到惊讶?在这种情况下,什么是不正确的?
\n我认为示例中主要令人困惑的事情是 \xe2\x80\x9csuper.play()\xe2\x80\x9d 是合法的,并且与最后一个继承的成员 - TC 相关。我认为这只是我们只采用最后一个时的解决方法。\n我想他们可以通过此解决方法解决第一种情况(不\xe2\x80\x99t 编译) - 只需采用最后一个继承的实现。
\n