我在Scala中尝试多重继承。我知道有一个从右到左的解决方案,但我不理解override
关键字的作用。让我们考虑以下片段:
trait A { def method }
class B extends A { def method = println("B") }
trait C extends A { override def method = println("C") }
trait E { }
class D extends B with C with E
它编译得很好,但如果我从定义override
的最右边的特征中删除method
,它就会被破坏。为什么是这样 ?即使没有关键字,这个方法也不会被覆盖吗?
答案 0 :(得分:3)
如果某个特征应该替换(而不是提供缺少的实现)方法,则需要使用override
关键字。无论其他方法是以特征还是以其他方式提供,都是如此。例如:
trait X { def foo = "foo" }
class Y { def foo = "bar" }
class Z extends Y with X // Does not compile
所以它与抽象类的规则完全相同:你需要覆盖你替换它的实现的方法(而不是第一次提供)。
请注意,对于traits,只要最后提供的方法是覆盖,就足够了:
trait L { def m: String }
trait M extends L { def m = "m" }
trait N extends L { def m = "M" }
trait O extends L { override def m = "?" }
class P extends M with N with O // All good
class Q extends M with N { override def m = "." } // Also good
这里,被称为“已经提供”的是扩展的早期部分,而且一切都很好。所以
class R extends O with N
不起作用,因为O
提供m
的实现(如果需要可以覆盖),但是N
然后尝试应用另一个,并且不允许覆盖。
另一方面,P
很好,因为即使M
和N
都尝试为m
提供实施,{{1}}也是最后一个,声明它的实现可以覆盖。它确实如此,一切都很好。