【问题标题】:What are scala's rules for resolving conflicting implicit valuesscala解决冲突隐含值的规则是什么
【发布时间】:2015-12-09 21:40:42
【问题描述】:

给定以下代码:

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

【问题讨论】:

  • 在 scala 中使用隐式时的个人规则 #1:在范围内永远不要有多个相同类型,因为你永远不知道谁在覆盖谁。

标签: scala


【解决方案1】:

子类型获胜:

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 更具体。


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

【讨论】:

    猜你喜欢
    • 2011-11-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-06-08
    • 1970-01-01
    • 1970-01-01
    • 2021-04-13
    相关资源
    最近更新 更多