我正在尝试理解“隐式”操作的使用:
class foo {
def x : Int = 12
}
object foo {
implicit def intToFoo(x : Int ) : foo = new foo
}
object bar {
implicitly[foo](1).x
}
以上编译。但我无法弄清楚为什么需要“隐式”操作。在我看来,因为'目标伴随对象'包含隐式转换,它应该自动发生。
答案 0 :(得分:2)
implicitly
(我已经看到)的一个常见用途是使用context bound类型参数。
回想一下,类型参数可以通过要求"证据来限制类型类:
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
,但如果你想要干净的上下文绑定语法,只需要隐式参数一次或两次,有时被认为是值得的权衡。
答案 1 :(得分:1)
这里并不是真的需要它。你也可以逃脱
object bar {
import foo._
1.x
}
因为导入foo._
也会将隐式转换带入隐式范围,因此1
会自动包装到foo
中,从而获得"方法x
。
在您的代码中使用implicitly
是相当罕见的,因为它实际上只是类型归属的替代:
object bar {
(1: foo).x
}
类型归属也有效,因为现在您再次提到您希望1
为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
作为第一个参数。由于Int
不是foo
,编译器会继续搜索从Int
到foo
的适用隐式转换。它看起来的一个地方是foo
的伴侣对象。因此,编译器会插入intToFoo
:
randomOtherFunction(intToFoo(1), 42).x
并且一切都在编译。