2010-05-05 56 views
8

给定两个独立的特质:撰写独立的特质

trait T1 { 
    def x = 42 
} 

trait T2 { 
    def x = 0 
} 

如果我尝试定义这两个特质:一类混合:

class C extends T1 with T2 

我得到一个编译错误:

error: overriding method x in trait T1 of type => Int; 
method x in trait T2 of type => Int needs `override' modifier 
class C extends T1 with T2 
    ^
one error found 

现在假设T1和T2是独立开发的,因此没有覆盖,因为它们不覆盖任何东西。那么C如何定义呢?像这样:

class C extends T1 with T2 { 
    override def x = super.x 
} 

回答

10

这就是所谓的diamond problem。在Scala中有两种方法来解决这个问题:

trait T1 { 
    def x = 0 
} 

trait T2 { 
    def x = 42 
} 

class C extends T1 with T2 { 
    override def x = super.x 
} 

class D extends T2 with T1 { 
    override def x = super.x 
} 

如果你现在打电话new C().x,你会得到42因为Scala使用您在过去的混合特征的实现。顺便说一下,new D().x将产生0。这意味着,为了解决钻石问题,你必须明确地定义你想要使用的实现。

另一种方法是如下:

trait T { 
    def x: Int 
} 

trait T1 extends T { 
    override def x = 0 
} 

trait T2 extends T { 
    override def x = 42 
} 

class C extends T1 with T2 

new C().x调用仍然会产生42因为T2是最后的性状的混合不同的是,你不必在C定义x

+0

这很有趣。如果'T1'和'T2'中'x'的两个定义有不同的类型,这似乎是一个不可避免的问题。 如果类型不匹配,Scala中是否有一种巧妙的方法来修复这些名称冲突? – Mike 2010-05-05 23:06:30

+0

使用我的第一个例子,然后定义'C'如下:'class C用T2 {override def x = super [T1] .x}'扩展T1。当然,你也可以调用'super [T2] .x'。 – 2010-05-06 04:04:26