我试图了解“隐式”操作的使用:
class foo {
def x : Int = 12
}
object foo {
implicit def intToFoo(x : Int ) : foo = new foo
}
object bar {
implicitly[foo](1).x
}
以上编译。但我无法弄清楚为什么需要“隐式”操作。在我看来,因为“目标伴随对象”包括隐式转换,它应该自动发生。
我试图了解“隐式”操作的使用:
class foo {
def x : Int = 12
}
object foo {
implicit def intToFoo(x : Int ) : foo = new foo
}
object bar {
implicitly[foo](1).x
}
以上编译。但我无法弄清楚为什么需要“隐式”操作。在我看来,因为“目标伴随对象”包括隐式转换,它应该自动发生。
implicitly(我见过的)更常见的用途之一是在使用上下文绑定类型参数时。
回想一下,可以通过要求“证据”将类型参数限制为类型类:
def f[N](n :N)(implicit ev :Numeric[N]) :Boolean = ???
这可以通过使用上下文绑定语法变得更简洁。
def f[N :Numeric](n: N) :Boolean = ???
但是现在我们没有可以ev使用的隐式参数。这并不总是一个问题。通常你需要类型限制但你不需要证据参数。但是,如果您确实需要该参数,那么解决问题的一种方法是通过implicitly.
def f[N :Numeric](n: N) :Boolean = {
val nn = implicitly[Numeric[N]].negate(n)
. . .
}
这增加了一些开销,因为隐式被解析了两次,一次作为(现在隐藏的)隐式参数,再次通过implicitly,但是如果你想要干净的上下文绑定语法,并且只需要一次或两次隐式参数,有时是被视为一个值得的权衡。
这里并不是真的需要。你也可以逃脱
object bar {
import foo._
1.x
}
因为导入foo._也会将隐式转换带入隐式范围,因此1会foo自动包装到 a 中,从而“获取”方法x。
在您的代码中使用implicitly相当少见,因为它本质上只是类型归属的替代品:
object bar {
(1: foo).x
}
类型归属也有效,因为现在您再次提到您希望1是 type foo,因此编译器将在隐式范围内搜索foo合适的隐式转换。
即使您不导入任何隐式转换,您的代码也不会implicitly以任何重要方式依赖。foo任何其他需要: import scala.language.implicitConversions的函数都会发生同样的情况
class foo {
def x : Int = 12
}
object foo {
implicit def intToFoo(x : Int ) : foo = new foo
}
def randomOtherFunction(a: foo, i: Int): foo = a
object bar {
randomOtherFunction(1, 42).x
}
在这里,就像在您的示例中一样implicitly,该函数randomOtherFunction需要一个foo作为第一个参数。由于Intis not a foo,编译器继续搜索从Intto的适用隐式转换foo。它看起来的地方之一是 的伴生对象foo。因此,编译器插入intToFoo:
randomOtherFunction(intToFoo(1), 42).x
一切都会编译。