請考慮以下代碼片段。 + =不是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?