标签:
1.Scala的类层级
Scala里类的顶端是Any所有的类都继承Any类,Any包括以下几个通用方法:
final def ==(that: Any): Boolean final def !=(that: Any): Boolean def equals(that: Any): Boolean def hashCode: Int def toString: String
2个操作符的重载,一个equals方法一个hashCode方法与一个toString方法。
根类Any有两个子类:AnyVal和AnyRef
AnyVal是值类型的父类,AnyRef是引用类型的父类。
下面是Scala的层级图:
值类从Any继承他的所有方法:
println(42.toString) println(42.hashCode) println(42.equals(42))
需要的时候,类scala.Int的实例可以自动放宽(通过隐式转换)到类scala.Long的实例。
隐式转换还用来为值类型添加更多的功能。例如,类型Int支持以下所有的操作:
println(42 max 43) println(1 until 5) println(1 to 5) println(3.abs) println((-3).abs)
这些都是怎么实现的?实际上,Scala以与Java同样的方式存储整数:把它当作32位的字。
这对在JVM上的效率以及与Java库的互操作性方面来说都很重要。
标准的操作如加法或乘法都被实现为原始操作。
然而,当整数需要被当作(Java)对象看待的时候,Scala使用了“备份”类java.lang.Integer。
如在整数上调用toString方法或者把整数赋值给Any类型的变量时,就会这么做。需要的时候,Int类型的整数能被透明转换为java.lang.Integer类型的“装箱整数”。
所有这些听上去都近似Java5里的自动装箱并且它们的确很像。
不过有一个关键差异,Scala里的装箱比Java里的更少看见。尝试下面的Java代码:
boolean isEqual(int x,int y) { return x == y; } System.out.println(isEqual(421,421)); 你当然会得到true。 现在,把isEqual的参数类型变为java.lang.Integer(或Object,结果都一样): // Java代码 boolean isEqual(Integer x, Integery) { return x == y; } System.out.println(isEqual(421,421));
你会发现你得到了false!
原因是数421被装箱了两次,因此参数x和y是两个不同的对象。
因为在引用类型上==表示引用相等,而Integer是引用类型,所以结果是false。
这是展示了Java不是纯面向对象语言的一个方面。我们能清楚观察到原始类型和引用类型之间的差别。
现在在Scala里尝试同样的实验:
object Test extends App { def isEqual(x:Any,y:Any) = x == y println(isEqual(1,1)) }
实际上Scala里的相等操作==被设计为透明的参考类型代表的东西。
对值类型来说,就是自然的(数学或布尔)相等。
对于引用类型,==被视为继承自Object的equals方法的别名。
这个方法被初始地定义为引用相等,但被许多子类重载实现它们种族的相等概念。
这也意味着Scala里你永远也不会落入Java知名的关于字串比较的陷阱
。Scala里,字串比较以其应有的方式工作:
val x = new String("abc") val y = new String("abc") println(x == y) /*比较引用是否相等 */ println(x eq y) /*比较引用是否不相等*/ println(x ne y)
3底层类型
在图释类型层级的底部你看到了两个类scala.Null和Scala.Nothing。它们是用统一的方式处理某些Scala的面向对象类型系统的“边界情况”的特殊类型。
类Null是null类型的引用;它是每个引用类(就是说,每个继承自AnyRef的类)的子类。Null不兼容值类型。你不可,比方说,把null值赋给整数变量。
类型Nothing在Scala的类层级的最底端;它是任何其它类型的子类型。
然而,根本没有这个类型的任何值。
要一个没有值的类型有什么意思呢?7.4节中讨论过,Nothing的一个用处是它标明了不正常的终止。
例如Scala的标准库中的Predef对象有一个error方法,如下定义:
def error(message:String): Nothing = throw new RuntimeException(message)
error的返回类型是Nothing,告诉用户方法不是正常返回的(代之以抛出了异常)。因为Nothing
是任何其它类型的子类,你可以非常灵活的使用像error这样的方法。例如:
def divide(x:Int, y:Int): Int = if(y != 0) x / y else error("can‘t divide by zero")
“那么”状态分支,x / y,类型为Int,而“否则”(else)分支,调用了error,类型为Nothing。
因为Nothing是Int的子类型,整个状态语句的类型是Int,正如需要的那样。
标签:
原文地址:http://www.cnblogs.com/qugangf/p/4377290.html