好吧,如果您考虑如何表示 Char,则 Char 是一个无符号的 16 位字段,范围从 (0 到 2^16 - 1)。这可以适合Int(32 位有符号,范围从 -2^31 到 2^31 - 1)中没有溢出。
Scala 的一些基本类型,按照它们的表示长度(以位为单位):
-
Byte(8)
-
Char (16)
-
Int (32)
-
Long (64)
除Char 外,所有都已签名,并且都可以转换为“低于”它的类型,因为它们永远不会溢出/不足(Byte 到 Char 除外,它不存在)。在Predef 中查看所有这些隐式转换。
这就是我认为存在隐式转换的原因 - 允许存在如下表达式:
def foo(c: Char) { println(c) }
foo('a' + 2) // prints c
另一种解释与您给出的解释类似(Char 只是一个数字......)。对我来说,这很有意义——所有Chars 的集合都包含在所有Ints 的集合中,因此,applying my own guidelines for using implicits 的转换应该是隐式的。
我确实理解您的烦恼,因为我喜欢编译器发出错误信号,就像您刚才举的例子一样。如果 Scala 有办法关闭隐式转换(或关闭特定隐式转换,因为将它们全部关闭可能会造成严重破坏!)
对于您的问题,我看到的唯一解决方案是使用 Map[RichChar, Int] 或类似的东西 - RichChar 被隐式转换为 Int,因为无法链接隐式转换。 EDIT 发现实际上没有从RichChar 到Char 的隐式转换。
def foo(x: Int) = x + 1
import scala.runtime.RichChar
val ch = 'a'
val rch = new RichChar('a')
foo(ch) // compiles fine
// foo(rch) // does not compile
def bar(ch: Char) = println(ch)
// bar(rch) // oops... does not compile
implicit def rch2char(rch: RichChar): Char = rch.self.asInstanceOf[Char]
bar(rch) // yay!
编辑:实际上,如果您仔细了解 Scala API,Char 确实有一个重载的 + 方法,它接受一个 Int 参数。 Int 也是如此。这可能与底层 JVM 做了类似的事情有关。
还请注意,我给您的示例与允许将Ints 添加到Chars 无关! API 已经允许这样做。更微妙的一点是,当您将Int 添加到Char 时,您会得到一个Int。隐式转换允许将此添加的结果用作Char。
还要注意我给出的更理论的答案 - Char 是 Int 的子集!
-- Flaviu Cipcigan