【问题标题】:List of String implicit conversions like +=字符串隐式转换列表,如 +=
【发布时间】:2011-08-29 19:07:34
【问题描述】:

考虑以下sn-p。 += 不是 java.lang.String 的成员,所以我想有某种隐式转换正在进行。如何找到作用于 String 的此类预定义隐式转换的列表?

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

scala> x += x

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

【问题讨论】:

    标签: scala implicit-conversion


    【解决方案1】:

    你选择了一个特别糟糕的例子。在某种意义上,+=String 的一部分。请参阅java.lang.String 的 Javadoc 上的此评论:

    Java 语言为字符串提供了特殊的支持 连接运算符 (+),并将其他对象转换为 字符串。

    您必须查找 Java language specification 才能找到有关它的更多信息 (15.18.1)。但是,Scala 不是 Java,所以 + 也是 Scala language specification (12.3.1) 的一部分。

    到目前为止,我说的是+,而不是+=。然而,Scala 有一个特殊的赋值语法糖。如第 6.12.4 节所述,除了<=>=!= 和以= 开头的运算符外,任何以等号结尾的运算符符号(参见第 1 章中的“运算符字符”)都将如果它不作为方法存在,则被重新解释。具体来说,

    x += 1
    

    将被重新解释为

    x = x + 1
    

    无论x 是否为var,都会发生这种情况,因此有时可能会看到错误消息“reassignment to val”。

    所以,如您所见,+= 确实是 String 的一部分,通过 Java 规范中的一个异常被复制到 Scala 规范,加上一些语法糖。

    这并不意味着java.lang.String 中没有可以通过隐式转换使用的方法。但是,我将把它留给其他答案。如果我是你,我会改变问题中的方法,使其正确。此外,+= 在 Stack Overflow 中是无法搜索到的。

    【讨论】:

      【解决方案2】:

      您需要查看scala.Predef - 在那里定义的所有隐式将始终在范围内(因此您不需要导入它们)。

      如果你查看it's source code,你会发现这个部分:

      // Strings and CharSequences ------------
      
      ...
      
      implicit def augmentString(x: String): StringOps = new StringOps(x)
      implicit def unaugmentString(x: StringOps): String = x.repr
      
      ...
      

      【讨论】:

        【解决方案3】:

        StringOps 定义 String 的隐式转换。它与其他有用的东西一起被导入到scala.Predef 的作用域中。

        【讨论】:

          【解决方案4】:

          不特定于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。有关详细信息,请参阅 Daniel Sobral 对以下内容的回答:Where does Scala look for implicits?

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2023-03-24
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多