2017-05-24 67 views
1

我正在尝试Scala中的一些东西,来自Python。由于Scala是很多更严格的保守类型一致的,我很惊讶地发现,我可以做以下的串联,这将在Python炸毁:为什么我可以在Scala中连接字符串和Int?

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

adder("word", "suffix") 

res13:字符串= wordsuffix

但也:

val x:Int = 1 

adder(x, "suffix") 

res12:字符串= 1suffix

  • 所以它只是一个转化成Int一个String瓦特/输出告诉我。这叫做什么?它背后的逻辑是什么?

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

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

+1

如果你的问题真的** _为什么_ **这是如此在斯卡拉而不是** _这是怎么做的,我怀疑这是这样做的,因为在Java(主要目标平台)见[5.4。字符串转换](https://docs.oracle.com/javase/specs/jls/se7/html/jls-5.html#jls-5.4)以及.Net(历史上的其他目标平台),它就是这样工作的。至于它为什么在那里,我认为是因为一些典型用法的方便。 – SergGr

回答

3

有一个在scala.Predef上任何类型的

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

实现Any + String的对象进行操作(如您已在adder它定义)的隐式类。正如流氓所提到的那样,还有一种连接String + Anydefined in StringOps的方法。如果您尝试执行Any + Any,那么它会失败,因为它期望以String作为参数。

所以它只是转变的诠释为一个字符串瓦特/告诉我

Scala是将您的IntString,但它不是一个类型转换,因为Int不能被强制转换为String。你可以观察到,通过尝试这样的:

这将无法编译,因为Scala不能强迫神奇的IntString

背后的逻辑是什么?

implicit classes

什么是这样做的好处?我感觉它会回来咬我,例如当处理用户对功能的输入时。

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

+0

@ rogue-one谢谢,这很有道理!这样做是正确的,这是有效的,因为:'+'这个特定的实例在一边有一个'String',其中''是以这种方式实现的;并且:无论什么原因,Scala设计者在这种环境下认为“Any”被视为“String”? – patrick

+1

是的,没错。右侧的任何其他类型(例如'Any + Any')都会产生错误。 – Samuel

+2

实际上,我认为这与Scala设计师认为这不是一个好主意,更多的是与Java兼容是因为Java允许您用魔术般地将对象与'String'连接起来。 – Samuel

1

该字符串连接不仅适用于Int,而且适用于任何数据类型。例如

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

scala> "Hello" + Elephant("elephant") 
res2: String = HelloElephant(elephant) 

这是因为(通过PREDEF)在StringOps定义的method+类接受任何类型的参数。所以它是一个通过隐式转换可用于String对象的方法,该方法接受类型为Any的参数。所以"Hello" + Elephant("elephant")实际上是"Hello".+(Elephant("elephant"))

1
  • 这就是所谓的隐式转换(或隐式类型转换)
  • 目的 - 方便,这样你就不必手工做的一切。大多数高级语言会做与像字符串,整数,布尔变量最常用的仿制药...

您可以检查scala.Predef时看到隐式类型转换使用的所有方法,你可以控制它使用scala.language.implicitConversions。阅读更多在Scala Documentation

相关问题