2013-10-10 39 views
1

有一個情況我得到一個編譯器錯誤的隱式轉換,如果我不包括清單:「曖昧參考超載定義」隱式轉換,而不清單

import scala.language.implicitConversions 

abstract class Thing[+A] { 
    def get:A 
} 

case class SubThing[+A](a:A) extends Thing[A] { 
    def get = a 
} 

object Thing { 
    implicit def anyToThing[A](a:A):Thing[A] = SubThing(a) 
} 

object Funcs { 
    def f(x:Thing[Int]) = x.get + 1 
    def f(x:Thing[Double]) = x.get + 1.0 
} 

object Main { 
    def main(args:Array[String]) = { 
    println(Funcs.f(1)) 
    } 
} 

會給

error: ambiguous reference to overloaded definition, 
     both method f in object Funcs of type (x: Thing[Double])Double 
     and method f in object Funcs of type (x: Thing[Int])Int 
     match argument types (Int) and expected result type Any 
println(Funcs.f(1)) 
      ^

然而,如果我通過在一個隱式清單對於A在隱式轉換:

import scala.language.implicitConversions 

abstract class Thing[+A] { 
    def get:A 
} 

case class SubThing[+A](a:A) extends Thing[A] { 
    def get = a 
} 

object Thing { 
    implicit def anyToThing[A:Manifest](a:A):Thing[A] = SubThing(a) 
} 

object Funcs { 
    def f(x:Thing[Int]) = x.get + 1 
    def f(x:Thing[Double]) = x.get + 1.0 
} 

object Main { 
    def main(args:Array[String]) = { 
    println(Funcs.f(1)) 
    } 
} 

導致代碼編譯正常。爲什麼會這樣?在我們的代碼庫中有一個真實的例子,如果您依賴於通用情況下的隱式轉換(通過顯式創建包裝類來消除這種隱式轉換),那麼會出現很多'沒有T的錯誤清單'錯誤;然而,如果我們能夠將Manifest從隱含的轉換中解脫出來,那將是理想的。爲什麼需要它,或者有另一種方法來完成同樣的事情,同時避免清單?

回答

1

這是由scala自動將Ints提升爲Double造成的,這導致隱式轉換不明確。包含清單時,它會創建一個隱式參數,使得函數解析變得明確,就像DummyImplicit隱式參數用於解決由於類型擦除而導致的重載函數模糊一樣,如Ivan所述。

0

我相信會發生這種情況,因爲一旦轉換爲Thing,輸入擦除將不再是Thing [Int]或Thing [Double]而是Thing [_],因此下面的方法重載不起作用。

object Funcs { 
    def f(x:Thing[Int]) = x.get + 1 
    def f(x:Thing[Double]) = x.get + 1.0 
} 

清單是在我的理解打破了,因爲一點我從來沒有解決這一問題的不多,但我想這presevies的類型,這樣的方法重載的作品。

你可以用宏來解決這個問題,我相信,儘管這會阻止在編譯器肯定不知道的任何事情上調用Funcs.f()是Int或Double。