我正在努力加快Scala的速度,并且对关键字">隐式"的使用感到有些困惑。
我想我理解隐式参数的概念,其中参数没有显式传入,Scala 将搜索正确类型的值(在调用范围内(。
我对">隐式价值"的使用感到困惑。
请考虑以下代码片段:
case class DemoApp() {
implicit val foo = CustomerFoo()
}
这与传递给 DemoApp(( 类构造函数的参数有关吗?
有人可以澄清一下吗?
谢谢,约翰·
我想我理解隐式参数的概念,其中参数没有显式传入,
这只是硬币的另一面。
Scala 将搜索正确类型的值(在调用范围内(。
是的,但它不会只是接受任何随机值。只有显式标记为implicit
的值。
implicit
修饰符有四种用法,它们是成对相关的。
一对与隐式参数相关。当应用于参数列表中的参数时,implicit
表示"不需要显式提供此参数,可以在调用的上下文中搜索"。当应用于val
或object
时,反过来,它意味着"这个值可以作为隐式参数传递"。
另一对与隐式转换有关。当implicit
应用于具有一个参数的方法的方法定义时,它意味着"每当您需要返回类型的值,但只有参数类型的值时,可以使用此方法从参数值转换为返回值"。
例如,如果我有这样的东西:
implicit def string2Tuple2(s: String): (Int, Int) = {
val l = s.split(",")
(l(0).toInt, l(1).toInt)
}
然后,每当 Scala 期望一个(Int, Int)
时,我也可以传递一个String
,Scala 知道它可以调用string2Tuple
来转换它:
val m = Map.empty[Int, Int]
m + "2,3"
//=> val res1: scala.collection.immutable.Map[Int,Int] = Map(2 -> 3)
这当然是一个愚蠢的例子。一个更有用的示例是enrich-my-library 习惯用法,其中我们创建一个新类,该类使用一些新功能增强现有类,然后提供从旧类型到扩充类型的隐式转换:
class HelloString(s: String) {
val hello = "Hello " + s + " World"
}
implicit def string2HelloString(s: String) = new HelloString(s)
"beautiful".hello
//=> val res2: String = Hello beautiful World
这就是implicit
修饰符的第二个用途。implicit
类只是包装类的语法糖+隐式转换,这意味着上述内容完全等同于:
implicit class string2HelloString(s: String) {
val hello = "Hello " + s + " World"
}
这就是implicit
修饰符在两个相关对中的四种用法。