为什么我可以在Scala中连接字符串和Int?

为什么我可以在Scala中连接字符串和Int?,scala,types,Scala,Types,我正在用Scala测试一些东西,来自Python。由于Scala在保持类型一致性方面要严格得多,我惊讶地发现,我可以进行以下串联,这在Python中可能会失败: def adder(one:Any, two:String) = {one+two} adder("word", "suffix") res13:String=wordsuffix 而且: val x:Int = 1 adder(x, "suffix") res12:String=1suffix 所以它只是把一个Int转换成一

我正在用Scala测试一些东西,来自Python。由于Scala在保持类型一致性方面要严格得多,我惊讶地发现,我可以进行以下串联,这在Python中可能会失败:

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

adder("word", "suffix")
res13:String=wordsuffix

而且:

val x:Int = 1

adder(x, "suffix")
res12:String=1suffix

  • 所以它只是把一个
    Int
    转换成一个
    String
    w/out告诉我。这叫什么?背后的逻辑是什么

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


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

这个字符串连接不仅适用于Int,而且适用于任何数据类型。比如说

scala> case class Elephant(value: String)
defined class Elephant

scala> "Hello" + Elephant("elephant")
res2: String = HelloElephant(elephant)
这是因为StringOps(通过Predef)类中定义了
+
,该类接受任何类型的参数。因此,它是一种通过隐式转换使String对象可用的方法,隐式转换接受类型为
Any
的参数。所以“你好”+大象(“大象”)实际上是“你好”+(大象(“大象”)

  • 它被称为隐式转换(或隐式类型转换)
  • 目的-方便,因此您不必手动执行所有操作。大多数高级语言都会使用最常用的泛型,如字符串、int、bools

您可以选中
scala.Predef
查看隐式转换类型时使用的所有方法,并且可以使用
scala.language.implicitConversions
控制它。更多信息请访问。

scala.Predef中有一个隐式类,可对任何类型的对象进行操作

  implicit final class any2stringadd[A](private val self: A) extends AnyVal {
    def +(other: String): String = String.valueOf(self) + other
  }
它实现了
任意+字符串
(正如您在
加法器
中定义的那样)。正如rogue one提到的,还有一种方法可以连接
String+Any
。如果您尝试执行
Any+Any
,它将失败,因为它需要一个
字符串作为参数

所以它只是把一个Int转换成一个字符串w/out告诉我

Scala正在将您的
Int
转换为
String
,但这不是类型转换,因为
Int
无法强制转换为
String
。您可以通过尝试以下方式观察到:

def foo(str: String) = ???
foo(5)  // Type mismatch: expected: String, actual: Int
这将无法编译,因为Scala无法神奇地将
Int
强制为
String

背后的逻辑是什么

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


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

还有@rogue one谢谢,这很有意义!我想说对了,这是因为:
+
的这个特定实例的一侧有一个
字符串,其中
+
是这样实现的;而且:
Any
被视为一个
字符串
,不管是什么原因,这是Scala设计师认为在这个设置中最合理的?是的。右边的任何其他类型(例如,
Any+Any
)都会产生错误。事实上,我认为这与Scala设计师认为这是个好主意无关,更重要的是要与Java兼容,因为Java允许您神奇地将对象与
String
连接起来。如果您的问题是为什么Scala中会出现这种情况,而不是如何做到这一点,我怀疑这是通过这种方式实现的,因为在Java(主要目标平台)中,请参见以及在.Net中(历史附加目标平台)它是这样工作的。至于为什么会有它,我认为是因为在一些典型的用法中很方便。