为什么我可以在 Scala 中连接 String 和 Int?

pat*_*ick 3 types scala

我正在 Scala 中尝试一些来自 Python 的东西。由于 Scala 在保持类型一致方面更加严格,我惊讶地发现我可以执行以下连接,这在 Python 中会爆炸:

def adder(one:Any, two:String) = {one+two}

adder("word", "suffix")
Run Code Online (Sandbox Code Playgroud)

res13:字符串=字后缀

但是也:

val x:Int = 1

adder(x, "suffix")
Run Code Online (Sandbox Code Playgroud)

res12: 字符串 = 1 后缀

  • 所以它只是将 anInt转换为Stringw/out 告诉我。这叫什么,背后的逻辑是什么?

  • 这样做有什么好处?我觉得它会回来咬我,例如在处理用户对函数的输入时。

我知道这不是很具体,如果这太宽泛了,我很乐意收回这个问题。

Sam*_*uel 5

有一个隐式类scala.Predef可以操作任何类型的对象

  implicit final class any2stringadd[A](private val self: A) extends AnyVal {
    def +(other: String): String = String.valueOf(self) + other
  }
Run Code Online (Sandbox Code Playgroud)

这实现了Any + String(正如您在 中定义的那样adder)。正如 rogue-one 所提到的,还有一种在 中String + Any 定义StringOps的连接方法。如果您尝试这样做Any + Any,它将失败,因为它期望 aString作为参数。

所以它只是将 Int 转换为 String 而不告诉我

Scala 正在将 yourInt转换为String,但它不是类型转换,因为Int不能强制转换为String。你可以通过尝试这样的事情来观察:

def foo(str: String) = ???
foo(5)  // Type mismatch: expected: String, actual: Int
Run Code Online (Sandbox Code Playgroud)

这将无法编译,因为 Scala 不能神奇地将 an 强制Int转换为String.

它背后的逻辑是什么?

查看隐式类

这样做有什么好处?我觉得它会回来咬我,例如在处理用户对函数的输入时。

这是一种非常特定于String和连接的便捷方法。这个特性是用 Java 实现的,所以我相信它是用 Scala 实现的,以保持源代码兼容性。我上面的例子表明(除了这种特定情况),用户对函数的输入将尊重函数上定义的类型。

  • 实际上,我认为这与 Scala 设计者认为这是一个好主意的关系不大,而更多地与与 Java 兼容有关,因为 Java 允许您神奇地将对象与 String 连接起来。 (2认同)