码迷,mamicode.com
首页 > Windows程序 > 详细

C#程序员的Scala之路第九章(Scala的层级)

时间:2015-03-30 11:03:49      阅读:209      评论:0      收藏:0      [点我收藏+]

标签:

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,正如需要的那样。

C#程序员的Scala之路第九章(Scala的层级)

标签:

原文地址:http://www.cnblogs.com/qugangf/p/4377290.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!