Список неявных преобразований типа String, таких как + = - PullRequest
3 голосов
/ 29 августа 2011

Рассмотрим следующий фрагмент.+ = не является членом java.lang.String, поэтому я предполагаю, что происходит какое-то неявное преобразование.Как найти список таких предопределенных неявных преобразований, действующих на строку?

scala> var x = "asdf"
x: java.lang.String = asdf

scala> x += x

scala> x
res2: java.lang.String = asdfasdf

Ответы [ 4 ]

13 голосов
/ 30 августа 2011

Вы выбрали особенно плохой пример.+= в некотором смысле является частью String.См. Этот комментарий в Javadoc для java.lang.String:

. Язык Java обеспечивает специальную поддержку оператора конкатенации строк (+) и преобразования других объектов в строки.

Вам придется поискать Спецификацию языка Java , чтобы найти больше информации об этом (15.18.1).Но, опять же, Scala не является Java, поэтому + также является частью спецификации языка Scala (12.3.1).

До сих пор я говорил о +,не +=.Тем не менее, Scala имеет специальный синтаксический сахар для назначения.Как описано в разделе 6.12.4, за исключением <=, >=, != и операторов, начинающихся с =, любой символ оператора (см. «Символы оператора» в главе 1), заканчивающийся знаком равенства, будетбыть переосмысленным, если он не существует как метод.В частности,

x += 1

будет интерпретироваться как

x = x + 1

Это произойдет независимо от того, является ли x var, поэтому иногда можно увидеть сообщение об ошибке "reassignment to val ".

Итак, как вы можете видеть, += действительно является частью String, за исключением исключения в спецификации Java, которое было реплицировано в спецификации Scala, плюс немного синтаксического сахара.

Это не означает, что в java.lang.String нет методов, которые можно использовать с неявными преобразованиями.Однако я оставлю это другим ответам.На вашем месте я бы изменил метод в вопросе, чтобы он был правильным.Кроме того, += невозможно найти в переполнении стека.

8 голосов
/ 29 августа 2011

Вам нужно искать в scala.Predef - все определенные здесь последствия всегда будут в области действия (поэтому вам не нужно их импортировать).

Если вы загляните в это исходный код , вы найдете этот раздел:

// Strings and CharSequences ------------

...

implicit def augmentString(x: String): StringOps = new StringOps(x)
implicit def unaugmentString(x: StringOps): String = x.repr

...
4 голосов
/ 30 августа 2011

Не относится только к String, но в Scala REPL есть удобная функция, позволяющая увидеть все последствия в объеме:

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]
  ...

Стоит также отметить, что импликации не обязательно должны быть применены. Например, мы можем определить неявное преобразование в сопутствующем объекте,

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 выполняется поиск последствий, поскольку целевой тип Foo. Для получения дополнительной информации см. Ответ Даниэля Собрала на: Где Scala ищет возможные последствия?

4 голосов
/ 29 августа 2011

StringOps определяет неявные преобразования для String. Он импортируется в область действия scala.Predef вместе с другими полезными вещами.

...