我正在Scala 中创建一个简单的函数
def addOne(m: Int): Int = m + 1
将它与整数一起使用正常,使用double会引发类型不匹配错误。
addOne(2) = 3
addOne(2.1) = error: type mismatch
当我将它与双引号中的字符一起使用时,它会引发预期的类型不匹配。
addOne("z") = error: type mismatch
但是,当使用单引号字符时,它会返回该字母的值。
addOne('z') = 123
这里发生了什么,为什么会这样?
之所以可以使用Char
作为接受Int
的函数的参数,是因为Scala执行从Char
到Int
的隐式转换。这个特定的转换是在Char
类的伴随对象中定义的。请参阅此处:
http://www.scala-lang.org/api/2.12.1/scala/Char$.html(看起来SO在$字符处断开了这个链接。改为复制粘贴)
执行转换的函数称为char2int
。它将Char
转换为相应的Unicode值作为Int
。
当Scala编译器发现类型Char
和Int
不匹配时,它将首先检查是否有任何可用的隐式转换。只有在找不到任何编译错误的情况下,它才会给出编译错误。如果它发现了一个隐式转换,它将把该函数调用插入到代码中。因此,您的代码被转换为:
addOne(Char.char2int('z'))
如果您想进行自己的隐式转换,例如,让您的函数接受String
,您可以定义如下:
// Enable implicit conversions.
import scala.language.implicitConversions
// The "implicit" modifier is the important part here, not the name of the function.
implicit def string2int(s: String) = s.toInt
现在编译:
// This returns 6
addOne("5")
/*
* This throws a NumberFormatException due to my implementation of string2int.
* Create your own implementation of string2int if you want it to work properly.
*/
addOne("a")
最后:注意隐式转换非常强大,因此可能很危险!有关解释,请参阅原型保罗的评论。
这是因为addOne(m: Int)
[冒号(:)]后面的部分告诉Scala你将传递Int给它,而不是Double,而不是其他任何东西。
如果你想让它为Double工作,试试这个,但你总是会得到Double作为结果。
def addone (m : Double ) = m+1
addone: (m: Double)Double
scala> addone(1)
res0: Double = 2.0
scala> addone(1.1)
res1: Double = 2.1
Scala使用ASCII表映射字符类型。因此,'z'
被映射到122,122是一个整数。在方法addOne('z')
中,输入参数被强制转换为整数(即122)。
然而,addOne(2.1)
中的输入参数是2.1,它是一个双参数,而addOne("z")
中的输入是一个字符串。它们不能自动转换为整数。
def addOne(m: Int): Int = m + 1
只接受m
的整数它也适用于单引号字符(z
),因为它被转换为ASCII值。"z"的值为122,然后加1。
scala>val foo:Int='z'
foo:Int=122
scala>val bar=foo+1
bar:Int=123
如果你想让它与double一起工作,你可以指定def addOne(m: Double): Double = m + 1