2015-12-08 23 views
2

考慮下面的代碼規則:什麼是Scala的解決衝突的隱含價值

/** 
    * Created by danap on 12/8/15. 
    */ 
object ImplicitTest { 
    trait EC { 
    override def toString : String = s"EC" 
    } 

    trait DEC extends EC { 
    def sub : EC 
    override def toString : String = s"DEC - $sub" 
    } 

    def usesEC(implicit ec : EC) = ec.toString 

    class B(implicit val dec: DEC) { 
    def whichEC = usesEC 
    } 

    class C(implicit val dec: DEC) { 
    implicit val _ec = dec.sub 

    def whichEC = usesEC 
    def whichECExplicit = usesEC(_ec) 
    } 

    def main(args:Array[String]): Unit = { 

    implicit val dec : DEC = new DEC { 
     val sub = new EC {} 
    } 

    val b = new B 
    val c = new C 

    println(s"b class = ${b.whichEC}") 
    println(s"c class = ${c.whichEC}") 
    println(s"c class = ${c.whichECExplicit}") 
    } 
} 

斯卡拉2.11的輸出是:

b class = DEC - EC 
c class = DEC - EC 
c class = EC 

我希望它是:

b class = DEC - EC 
c class = EC 
c class = EC 

因爲隱含的val _ec被聲明爲「更接近」調用usesECwhichEC。爲什麼會發生?另外,我可能會如何強制_ecC.whichEC中隱式使用?

+1

在scala中使用implicits時的個人規則#1:從來沒有超過一個相同類型的範圍,因爲你永遠不知道是誰在壓倒誰。 –

回答

2

子類型勝:

class Super    { override def toString = "Super" } 
class Sub extends Super { override def toString = "Sub" } 

// does not compile - ambiguous 
object Test1 { 
    implicit val s1 = new Super 
    implicit val s2 = new Super 

    println(implicitly[Super]) 
} 

// does not compile - ambiguous 
object Test2 { 
    implicit val s1 = new Sub 
    implicit val s2 = new Sub 

    println(implicitly[Super]) 
} 

object Test3 { 
    implicit val s1 = new Super 
    implicit val s2 = new Sub 

    println(implicitly[Super]) 
} 

Test3 // 'Sub' 

隱參數解析的規則在§7.2 of the Scala Language Specification定義:

如果有匹配的隱含參數的類型,最具體的哪幾個符合條件的參數將使用靜態重載分辨率的規則來選擇一個。

鏈接到§6.26.3,它涉及類型推斷。這裏一個類型A <: B給出了替代子類A1在替代超一流B的相對重量,使得A更具體B


一般而言,作爲註釋建議,應避免使多個不合格部件(前綴更小,即,其在默認位置通過伴侶發現例如對象隱含值)轉換成範圍。