作为我的另一个 question 的后续行动,请参阅代码中的评论/问题:
case class Implicit(name: String)
def foo(implicit i: Implicit = null) = println(Option(i))
def bar1(implicit i: Implicit) {
foo // prints None
implicit val i = Implicit("J") // Why is call to foo above affected although this line comes after?
foo // prints Some(Implicit(I))
}
def bar2(implicit i: Implicit) {
foo // prints None
implicit val i = null
implicit val j = Implicit("J")
foo // prints None // Why? Should raise ambiguous implicits or at least choose j.
}
def bar3(implicit i: Implicit) {
foo // prints None
val i = null
implicit val j = Implicit("J")
foo // prints Some(Implicit(J)) // Now it works as I expected to work in bar2.
}
def bar4(implicit i: Implicit) { // That's how I expected to see bar1 working. A ugly hack here.
foo // prints Some(Implicit(I))
locally {
val i = null
implicit val j = Implicit("J")
foo // prints Some(Implicit(J))
}
}
val i = Implicit("I")
bar1(i)
bar2(i)
bar3(i)
bar4(i)
最佳答案
您的代码受到名称隐藏的影响。 chapter 2中的规范对此说道:
A binding has a scope in which the entity defined by a single name can be accessed using a simple name. Scopes are nested. A binding in some inner scope shadows bindings of lower precedence in the same scope as well as bindings of the same or lower precedence in outer scopes.
在您的示例中,这意味着
def foo(implicit i: Implicit) = println(Option(i))
我们有以下可能性:
隐式参数
i
被传递到foo
因为x
将是一个前向引用:scala> def f(implicit i: Implicit) = {foo; implicit val x = Implicit("i")} f: (implicit i: Implicit)Unit
没有任何内容可以传递给
foo
因为参数i
被本地值i
遮挡它具有更高的优先级,但无法调用,因为它是前向引用。scala> def f(implicit i: Implicit) = {foo; implicit val i = Implicit("i")} <console>:11: error: could not find implicit value for parameter i: Implicit def f(implicit i: Implicit) = {foo; implicit val i = Implicit("i")} ^
当一个值具有相同的名称时,它会被隐藏,但它不能具有相同的类型:
scala> def f(implicit i: Implicit) = {implicit val j = Implicit("i"); foo} <console>:11: error: ambiguous implicit values: both value i of type Implicit and value j of type Implicit match expected type Implicit def f(implicit i: Implicit) = {implicit val j = Implicit("i"); foo} ^ scala> def f(implicit i: Implicit) = {val i = null; implicit val j = Implicit("i"); foo} f: (implicit i: Implicit)Unit
作用域中存在多个隐式,但其中一个具有更高的优先级。在这种情况下
i
具有更高的优先级,因为Null <: Implicit
scala> def f(implicit i: Implicit) = {implicit val i = null; implicit val j = Implicit("i"); foo} f: (implicit i: Implicit)Unit
您对 foo
的定义声明了隐式参数的默认值。这不会改变上述规则,但编译器可以在没有其他值可用时选择默认值。
关于scala - 隐式的范围,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25096097/