Scala 类定义中“隐式 val”的含义是什么?

Joh*_*hnB 2 scala implicit

我正在努力加快 Scala 的速度,但对关键字“ implicit ”的使用有点困惑。

我想我理解隐式参数的概念,其中参数没有显式传入,Scala 将搜索正确类型的值(在调用范围内)。

我对“隐式 val ”的使用感到困惑。

考虑以下代码片段:

case class DemoApp() {
   implicit val foo = CustomerFoo()
}
Run Code Online (Sandbox Code Playgroud)

这与传递到 DemoApp() 类构造函数的参数有关吗?

有人可以澄清一下吗?

谢谢,约翰B

Jör*_*tag 7

我想我理解隐式参数的概念,其中参数没有显式传入,

这只是硬币的另一面。

Scala 将搜索正确类型的值(在调用范围内)。

是的,但它不会只取任何随机值。仅限明确标记的值implicit

修饰符有四种用法implicit,它们成对相关。

一对与隐式参数相关。当应用于参数列表中的参数时,implicit意味着“不需要显式提供该参数,可以在调用的上下文中搜索它”。当应用于 aval或 anobject时,它意味着“该值可以作为隐式参数传递”。

另一对与隐式转换有关。当implicit应用于具有一个参数的方法的方法定义时,它的意思是“每当你需要一个返回类型的值,但你只有一个参数类型的值时,你可以使用此方法从参数值转换为返回值”。

例如,如果我有这样的东西:

implicit def string2Tuple2(s: String): (Int, Int) = {
  val l = s.split(",")
  (l(0).toInt, l(1).toInt)
}
Run Code Online (Sandbox Code Playgroud)

然后,每当 Scala 需要 a 时(Int, Int),我也可以传递 aString来代替,Scala 知道它可以调用string2Tuple来转换它:

val m = Map.empty[Int, Int]

m + "2,3"
//=> val res1: scala.collection.immutable.Map[Int,Int] = Map(2 -> 3)
Run Code Online (Sandbox Code Playgroud)

这当然是一个愚蠢的例子。一个更有用的示例是丰富我的库习惯用法,我们创建一个新类,用一些新功能增强现有类,然后提供从旧类型到丰富类型的隐式转换:

val m = Map.empty[Int, Int]

m + "2,3"
//=> val res1: scala.collection.immutable.Map[Int,Int] = Map(2 -> 3)
Run Code Online (Sandbox Code Playgroud)

这是修饰符的第二个用途implicitimplicit类只是包装类的语法糖 + 隐式转换,这意味着上面的内容完全等同于:

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
Run Code Online (Sandbox Code Playgroud)

implicit现在您已经看到了修饰符在两个相关对中的四种用法。