2012-04-26 89 views
3

下面的代碼片段避免繼承方法斯卡拉

class A { 
    def foo = "A.foo" 
} 

trait B { 
    def foo = "B.foo" 
    def bar = "B.bar" 
} 

val x = new A with B 

不編譯,因爲

error: overriding method foo in class A of type => java.lang.String; 
method foo in trait B of type => java.lang.String needs `override' modifier 

然而,我的本意是定義X,這樣:

x.foo => "A.foo" 
x.bar => "B.par" 

也就是說,我只想要x從B繼承欄,但不是foo。 scala有沒有辦法達到這個目的?

回答

12
scala> val x = new A with B { override def foo = super[A].foo } 
x: A with B = [email protected] 

scala> x.foo 
res0: java.lang.String = A.foo 

scala> x.bar 
res1: java.lang.String = B.bar 

這顯然不是你想要經常做的事情。

+0

+1這是一個巧妙的技巧... – Russell 2012-04-26 21:36:17

+1

還要注意,雖然它可以很好地與defs一起使用,但vals會變得更加棘手。 – 2012-04-26 21:39:34

5

因爲它似乎並不像你真的想A with B一個B,而是有機會獲得一個B的行爲的一個子集,這聽起來像在繼承一個很好的案例組成:

class A(val b: B) { 
    def foo = "A.foo" 
    def bar = b.bar 
} 

class B { 
    def foo = "B.foo" 
    def bar = "B.bar" 
} 

val x = new A(new B) 
x.foo => "A.foo" 
x.bar => "B.bar" 

或者,如果你需要一個A沒有B的大部分時間,但有時需要能夠調用bar方法就可以了,你可以用一個隱式轉換做到這一點:

class A { 
    def foo = "A.foo" 
} 
class B { 
    def foo = "B.foo" 
    def bar = "B.bar" 
} 

implicit def a2b(a: A) = new B 

val x = new A 
x.foo => "A.foo" 
x.bar => "B.bar"