什么是scala用于解决冲突隐含值的规则

时间:2015-12-08 20:06:41

标签: 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}")
  }
}

scala 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被宣布为“更接近”usesEC中对whichEC的调用。为什么会这样?另外,我如何强制_ec隐式使用C.whichEC

1 个答案:

答案 0 :(得分: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类型为备用超类A提供了替代子类1相对权重B,使A 更多具体而不是B

通常,正如评论所暗示的那样,您应该避免将多个不合格的成员(无前缀,即默认位置中的隐式值,例如通过伴随对象)带入范围。