2011-10-11 57 views
2

我有一個後續的問題是帶和不帶參數的重載方法定義的存在導致編譯錯誤的問題,這已經在這裏討論:Why is this reference ambiguous?Scala:對重載定義的模糊引用 - 最好的消歧?

總結一下:

trait A { 
    def foo(s: String) : String 
    def foo : String = foo("foo") 
} 
object B extends A { 
    def foo(s: String) : String = s 
} 
B.foo  // won't compile 

導致錯誤消息:

error: ambiguous reference to overloaded function 
both method foo in object B of type(s: String)String 
and method foo in trait A of type => String 
match expected type Unit 
B.foo 

一個可行的解決方案是提供編譯器與預期類型,如下所示:

val s: String = B.foo 

不幸的是,人們可能並不總是想引入額外的變量(例如,在一個斷言中)。一位在回答上面提到的以前的文章中推薦的至少兩倍的解決方案是用空括號調用該方法,像這樣:

B.foo() 

不幸的是,這導致了類似的編譯器錯誤(斯卡拉2.9.0.1 ):

(s: String)String <and> 
=> String 
cannot be applied to() 
B.foo() 

這是一個錯誤,還是錯誤的推薦解決方案? 而最終:有什麼選擇那裏做這個簡明,如:中

assert(B.foo == "whatever") 

代替

val expected : String = B.foo 
assert(expected == "whatever") 

感謝。

+0

'B'不能編譯,因爲你忘記提供特性'A'中'def foo:String'的實現。 – agilesteel

+0

@agilesteel對,在A上執行無副標題foo在傳輸中丟失了。現在修復了。錯誤仍然相同。 –

回答

6
assert((B.foo: String) == "whatever") 
+0

不錯,謝謝。這是我正在尋找的。 –

2

可以空括號添加到第二foo定義:

trait A { 
    def foo(s: String) : String 
    def foo() : String 
} 

然後你就可以刪除消歧爲其他地方所解釋:

assert(B.foo() == "whatever") 
+0

這也是一個很好的答案,謝謝。一個潛在的缺點是,如果無參數foo()僅在某些派生類中與超載替代方法發生衝突(例如,如果它比A更高),它仍然會強制所有調用,即使在A的兄弟之下,現在使用空括號來調用它(至少如果你不希望IDE在你離開括號時標記調用)。 –