请考虑以下代码片段。 + =不是java.lang.String的成员,所以我猜是有某种隐式转换正在进行。如何找到一个这样的预定义隐式转换作用于String的列表?字符串隐式转换列表,如+ =
scala> var x = "asdf"
x: java.lang.String = asdf
scala> x += x
scala> x
res2: java.lang.String = asdfasdf
请考虑以下代码片段。 + =不是java.lang.String的成员,所以我猜是有某种隐式转换正在进行。如何找到一个这样的预定义隐式转换作用于String的列表?字符串隐式转换列表,如+ =
scala> var x = "asdf"
x: java.lang.String = asdf
scala> x += x
scala> x
res2: java.lang.String = asdfasdf
你选了一个特别糟糕的例子。在某种意义上,+=
是String
的一部分。看到的Javadoc此评论为java.lang.String
:
Java语言提供特别支持的字符串 连接符(
+
),以及其他对象转换为字符串 。
你必须查找Java language specification才能找到更多关于它的信息(15.18.1)。但是,然后,Scala不是Java,所以+
也是Scala language specification(12.3.1)的一部分。
到目前为止,我所说的+
,而不是+=
。但是,斯卡拉有一个特殊的语法糖分配。如第6.12.4节所述,除<=
,>=
,!=
和以=
开头的运算符外,任何以等号结尾的运算符符号(请参见第1章中的“运算符”)将被重新解释,如果它不存在一个方法。具体来说,
x += 1
将被重新解释为
x = x + 1
不管x
是否是var
这会发生,所以人们可能会偶尔会看到一个错误信息“reassignment to val
”。
因此,正如您所看到的,+=
实际上是String
的一部分,通过在Scala规范中复制的Java规范中的例外情况以及一些语法糖。
这并不意味着java.lang.String
中没有方法可以通过隐式转换与它一起使用。但是,我会将其留给其他答案。如果我是你,我会改变问题中的方法,使其正确。另外,+=
在Stack Overflow中是不可测的。
你需要看看在scala.Predef - 被定义会有永远的范围(所以你不需要导入)所有implicits。
如果您在it's source code看,你会发现这节:
// Strings and CharSequences ------------
...
implicit def augmentString(x: String): StringOps = new StringOps(x)
implicit def unaugmentString(x: StringOps): String = x.repr
...
StringOps定义隐式转换为String
。它与其他有用的东西一起被导入scala.Predef
的范围。
并非专用String
,但斯卡拉REPL有一个实用的功能,看看范围所有的implicits:
scala> :implicits
No implicits have been imported other than those in Predef.
scala> :implicits -v
/* 96 implicit members imported from scala.Predef */
/* 66 inherited from scala.Predef */
implicit def Double2double(x: jl.Double): Double
implicit def byte2double(x: Byte): Double
implicit def char2double(x: Char): Double
...
/* 30 inherited from scala.LowPriorityImplicits */
implicit def genericWrapArray[T](xs: Array[T]): mutable.WrappedArray[T]
implicit def wrapBooleanArray(xs: Array[Boolean]): mutable.WrappedArray[Boolean]
implicit def wrapByteArray(xs: Array[Byte]): mutable.WrappedArray[Byte]
...
另外值得一提的是,implicits不必在适用范围。例如,我们可以在一个同伴对象定义的隐式转换,
case class Foo(s: String)
object Foo { implicit def string2Foo(s: String) = Foo(s.reverse) }
,然后应用它,即使它不在范围内,
scala> val f: Foo = "hello"
f: Foo = Foo(olleh)
的Foo
伴侣搜索对象implicits因为目标类型是Foo
。欲了解更多信息,请参阅Daniel Sobral的回答:Where does Scala look for implicits?