查看自动导入的scala的Predef
对象,我找到了following gem
implicit def char2int(x : Char) : Int
这导致一些低级错误潜入我的代码(在_1
中使用_2
代替Map[Char,Int]
。我真的不明白,为什么我要隐式地将Char
转换为Int
。拥有Char
类型(仅仅是一个数字)的整个想法是我不会将它用作数字(反之亦然)。
我使用scala的类型系统,以免出错!
我唯一(不好)的借口是与Java的可怕行为兼容。
更新:目前为止给出的两个答案给出的主要原因是隐式转换是为了支持Char
类型的有序操作。因此,例如'c'+1
会生成d
。如果这就是你想要的,你应该做的
class Char ...
...
def +(x:Int) = (this.toInt+x).toChar
def <(x:Char) = this.toInt < x.toInt
您可以根据自己的喜好添加和比较字符。 Char
仅为16位数字的事实意味着我们需要新的Word
(或Short
)类型。
答案 0 :(得分:5)
好吧,如果你考虑如何表示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
的集合都包含在所有Int
的集合中,因此,applying my own guidelines for using implicits,转换应该是隐含的。
我确实理解你的烦恼,因为我喜欢编译器发出错误信号,就像你刚才给出的那样。如果Scala有办法将隐式转换关闭(或者关闭特定的隐式转换,那么将它们全部关闭可能会造成严重破坏!)
我为您的问题看到的唯一解决方案是使用Map[RichChar, Int]
或类似内容 - RichChar
被隐式转换为Int
,因为隐式转换无法链接。 编辑发现实际上存在从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做类似的事实有关。
另请注意,我给你的例子与允许将Int
添加到Char
s无关!这已经被API允许了。更微妙的一点是,当您向Int
添加Char
时,您会获得Int
。隐式转换允许将此添加的结果用作Char
。
另请注意我给出的理论答案越多 - Char
是Int
的子集!
-- Flaviu Cipcigan
答案 1 :(得分:0)
这只是一个实现选择。有一段时间,许多语言确实在char
和int
之间存在很大差异,但由于它们总是必须具有转换函数,因此它实际上并没有非常阻塞,而确实只是变得很痛苦。
没有人真的想回到整个地方chr(n)
和ord(c)
的日子。想象一下UTF-8处理的乐趣。
一旦C出现char
s真的是int
s,它就会震动,即使在更强类型的语言中我们仍然坚持使用。
现在,如果您真的想要一个不会自动转换的封装Char
,那么就没有什么能阻止您为自己的代码定义新类型,比如说ElazarChar
。我怀疑你会讨厌它。