为什么我可以在Scala中连接字符串和Int?
我正在用Scala测试一些东西,来自Python。由于Scala在保持类型一致性方面要严格得多,我惊讶地发现,我可以进行以下串联,这在Python中可能会失败:为什么我可以在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转换成一
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
w/out告诉我。这叫什么?背后的逻辑是什么String
- 这有什么好处?我觉得它可能会回来咬我,例如,当处理用户对函数的输入时
我知道这不是很具体,如果这太宽泛,我很乐意收回这个问题。这个字符串连接不仅适用于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中(历史附加目标平台)它是这样工作的。至于为什么会有它,我认为是因为在一些典型的用法中很方便。