scala 解决冲突隐含值的规则是什么 [英] What are scala's rules for resolving conflicting implicit values

查看:43
本文介绍了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 的输出是:

The output for scala 2.11 is:

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 的调用.为什么会发生这种情况?另外,我如何才能强制 _ecC.whichEC 中隐式使用?

Because the implicit val _ec is declared "closer" to the call to usesEC in whichEC. Why does this happen? Also,how I might be able to force _ec to be used implicitly in C.whichEC?

推荐答案

子类型胜:

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 中定义Scala 语言规范:

The rules for resolution of implicit parameters are defined in §7.2 of the Scala Language Specification:

如果有多个符合条件的参数与隐式参数的类型匹配,则将使用静态重载解析规则选择一个最具体的参数.

If there are several eligible arguments which match the implicit parameter's type, a most specific one will be chosen using the rules of static overloading resolution.

这链接到处理类型推断的 §6.26.3.这里的类型 A <: B 给予替代子类 A 相对于替代超类 1 的相对权重B,使 A B 更具体.

This links to §6.26.3 which deals with type inference. Here a type A <: B gives the alternative sub-class A a relative weight of 1 over the alternative super-class B, making A more specific than B.

一般来说,正如评论所暗示的那样,您应该避免将多个不合格的成员(无前缀,即在默认位置找到的隐式值,例如通过伴随对象)引入作用域.

In general, as the comment suggests, you should avoid bringing multiple unqualified members (prefix-less, i.e. implicit values that are found in default locations for example through companion objects) into scope.

这篇关于scala 解决冲突隐含值的规则是什么的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆