Scala 隐含的范围
作为对我的另一个问题的跟进,请参见代码中的注释/问题:Scala 隐含的范围,scala,scope,implicit,Scala,Scope,Implicit,作为对我的另一个问题的跟进,请参见代码中的注释/问题: 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 alth
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)
您的代码存在名称阴影。中的规范说明了这一点: 绑定具有一个作用域,在该作用域中,可以使用简单名称访问由单个名称定义的实体。作用域是嵌套的某些内部作用域中的绑定会隐藏同一作用域中优先级较低的绑定以及外部作用域中优先级相同或较低的绑定。 在您的示例中,这意味着
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")}
^
您对
foo
的定义已使用隐式参数的默认值声明。这不会改变上述规则中的任何内容,但编译器可以在没有其他值可用时选择默认值。有趣!特别是3。(不得具有相同的类型)和4。!为什么i
具有更高的优先级,因为Null规则是子类型的优先级始终高于超类型。这就是为什么类型A;B
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
scala> def f(implicit i: Implicit) = {implicit val i = null; implicit val j = Implicit("i"); foo}
f: (implicit i: Implicit)Unit