为什么Scala隐式将Char转换为Int?

Ela*_*ich 9 types scala

看着Predef自动导入的scala 对象,我找到了以下gem

implicit def char2int(x : Char) : Int
Run Code Online (Sandbox Code Playgroud)

这已经引起了一些低俗的漏洞,潜入我的代码(用来_1代替_2Map[Char,Int]).我真的不明白,为什么我要隐式转换CharInt.拥有Char类型(仅仅是一个数字)的整个想法是我不会将它用作数字(反之亦然).

我使用scala的类型系统,以免出现这样的错误!

我唯一(坏)的借口是与Java的可怕行为兼容.

更新:到目前为止给出的两个答案给出的主要原因是隐式转换是为了支持对Char类型的有序动作.这样'c'+1就可以生成d.如果这就是你想要的,你应该这样做

class Char ...
    ...
    def +(x:Int) = (this.toInt+x).toChar
    def <(x:Char) = this.toInt < x.toInt
Run Code Online (Sandbox Code Playgroud)

你可以根据自己的喜好添加和比较字符.Char只有16位数的事实意味着我们需要一个新的Word(或Short)类型.

Fla*_*gan 5

好吧,如果你考虑a Char的表示方式,a Char是jusr无符号16位字段,范围从(0到2 ^ 16 - 1).这可以适合没有溢出Int(32位有符号,范围从-2 ^ 31到2 ^ 31 - 1).

Scala的一些基本类型按其位表示的长度顺序排列:

  • Byte (8)
  • Char (16)
  • Int (32)
  • Long (64)

所有都是签名的,除了Char和所有都可以转换为"低于"它的类型,因为它们永远不会过度/不足(除了Byteto Char,它不存在).查看Predef中的所有隐式转换.

这就是我认为存在隐式转换的原因 - 允许存在以下表达式:

def foo(c: Char) { println(c) }
foo('a' + 2) // prints c
Run Code Online (Sandbox Code Playgroud)

另一个解释是你所给出的那个(一个Char只是一个数字......).对我来说它确实有意义 - 所有的集合都Chars包含在所有Ints 的集合中,因此,应用我自己的指导来使用implicits,转换应该是隐含的.

我确实理解你的烦恼,因为我喜欢编译器发出错误信号,就像你刚才给出的那样.如果Scala有办法将隐式转换关闭(或者关闭特定的隐式转换,那么将它们全部关闭可能会造成破坏!)会很好.

我看到你的问题的唯一解决方案是使用Map[RichChar, Int]或类似的东西 - RichChar隐式转换为a Int,因为隐式转换无法链接.编辑发现,实际上有没有从隐式转换RichCharChar.

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!
Run Code Online (Sandbox Code Playgroud)

编辑:实际上,如果你仔细看看Scala API,Char确实有一个+Int参数的重载方法.同样如此Int.这可能与底层JVM做类似的事实有关.

另请注意,我给你的例子与允许向Ints 添加s 无关Char!这已经被API允许了.更微妙的一点是,当你添加Int一个Char,你得到一个Int.隐式转换允许使用此添加的结果作为Char.

还要注意我给出的更多理论答案 - Char是一个子集Int!

-- Flaviu Cipcigan