Scala的类层级:与Java类之异同

开发 后端
本文节选自Martin Odersky,Lex Spoon和Bill Venners所著,Regular翻译的《Programming in Scala》的第十一章。Scala是一种针对 JVM 将函数和面向对象技术组合在一起的编程语言。

Scala类层级图 

图释 11.1 Scala类层级图

51CTO编辑推荐:Scala编程语言专题

图释11.1展示了Scala的类层级的大纲。层级的顶端是类Any,定义了包含下列的方法:

  1. final def ==(that: Any): Boolean  
  2. final def !=(that: Any): Boolean  
  3. def equals(that: Any): Boolean  
  4. def hashCode: Int  
  5. def toString: String  

因为每个类都继承自Any,Scala程序里的每个对象都能用==,!=或equals比较;用hashCode哈希;和用toString格式化。类Any里的等号和不等号方法,==和!=,被声明为final,因此它们不能在子类里面重载。实际上,==总是与equals相同,!=总是与equals相反。因此独立的类可以通过重载equals方法剪裁==或!=的意义。我们会在本章后面展示一个例子。

根类Any有两个子类:AnyVal和AnyRef。AnyVal是Scala里每个内建值类的父类。有九个这样的值类:Byte,Short,Char,Int,Long,Float,Double,Boolean和Unit。其中的前八个对应到Java的原始类型,它们的值在运行时表示成Java的原始值。Scala里这些类的实例都写成文本。例如,42是Int的实例,'x'是Char的实例,false是Boolean的实例。你不能使用new创造这些类的实例。这一点被“小伎俩”,值类都被定义为即是抽象的又是final的,强制贯彻。因此如果你写了:

  1. scala> new Int  

你就会得到:

  1. < console>:5: error: class Int is abstract; cannot be instantiated  
  2. new Int  
  3. ˆ  

另一个值类,Unit,大约对应于Java的void类型;被用作不返回任何有趣结果的方法的结果类型。Unit只有一个实例值,被写作(),在7.2节中讨论过。

正如第五章中解释过,值类支持作为方法的通用的数学和布尔操作符。例如,Int有名为+和*的方法,Boolean有名为||和&&的方法。值类也从类Any继承所有的方法。你可以在解释器里测试: 

  1. scala> 42.toString  
  2. res1: java.lang.String = 42 
  3. scala> 42.hashCode  
  4. res2: Int = 42 
  5. scala> 42 equals 42 
  6. res3: Boolean = true 

注意,值类的空间是扁平的;所有的值类都是scala.AnyVal的子类型,但是它们不是互相的子类。代之以它们不同的值类类型之间可以隐式地互相转换。例如,需要的时候,类scala.Int的实例可以自动放宽(通过隐式转换)到类scala.Long的实例。

正如5.9节中提到过的,隐式转换还用来为值类型添加更多的功能。例如,类型Int支持以下所有的操作:

  1. scala> 42 max 43 
  2. res4: Int = 43 
  3. scala> 42 min 43 
  4. res5: Int = 42 
  5. scala> 1 until 5 
  6. res6: Range = Range(1234)  
  7. scala> 1 to 5 
  8. res7: Range.Inclusive = Range(12345)  
  9. scala> 3.abs  
  10. res8: Int = 3 
  11. scala> (-3).abs  
  12. res9: Int = 3 

这里解释其工作原理:方法min,max,until,to和abs都定义在类scala.runtime.RichInt里,并且有一个从类Int到RichInt的隐式转换。当你在Int上调用没有定义在Int上但定义在RichInt上的方法时,这个转换就被应用了。类似的“助推器类”和隐式转换存在于其它的值类。隐式转换将在第21章讨论细节。

类Any的另一个子类是类AnyRef。这个是Scala里所有引用类的基类。正如前面提到的,在Java平台上AnyRef实际就是类java.lang.Object的别名。因此Java里写的类和Scala里写的都继承自AnyRef。存在AnyRef别名代替使用java.lang.Object名称的理由是,Scala被设计成可以同时工作在Java和.Net平台。在.NET平台上,AnyRef是System.Object的别名。如此说来,你可以认为java.lang.Object是Java平台上实现AnyRef的方式。因此,尽管你可以在Java平台上的Scala程序里交换使用Object和AnyRef,推荐的风格是在任何地方都只使用AnyRef。

Scala类与Java类不同在于它们还继承自一个名为ScalaObject的特别的记号特质。理念是ScalaObject包含了Scala编译器定义和实现的方法,目的是让Scala程序的执行更有效。到现在为止,Scala对象包含了单个方法,名为$tag,用于内部以提速模式匹配。

【相关阅读】

  1. Scala中的Spiral程序:把代码都螺旋在一起
  2. Scala中变高变宽的实现:heighten和widen
  3. 学习Scala的定义工厂对象
  4. 如何实现Scala的above,beside和toString
  5. Scala学习:使用组合与继承

责任编辑:book05 来源: Artima
相关推荐

2010-01-15 09:15:09

Scala Actor并发

2009-06-16 17:54:38

Scala类语法语义

2009-07-22 07:53:00

Scala扩展类

2009-07-08 15:35:18

Case类Scala

2020-07-08 07:56:08

Java工具类包装类

2009-09-09 11:37:08

Scala的模式匹配

2009-09-09 11:28:40

Scala类

2009-09-28 11:37:03

Journal.scaKestrel

2009-07-20 16:56:51

Scala类的定义

2023-07-13 08:26:49

Java罗汉增强类

2021-04-05 08:11:04

Java基础Calendar类DateFormat类

2009-12-11 10:42:00

Scala讲座类定义构造函数

2009-07-21 17:29:25

Scala第一类函数

2009-07-21 11:25:03

ScalaRational类

2010-06-09 10:04:59

UML类图

2020-06-29 07:52:17

Java工具类开发

2015-08-06 15:13:49

runtimeIOS开发

2010-07-09 10:36:14

UML类图关系

2012-05-23 12:46:53

JavaJava类

2010-06-10 16:09:28

路由选择协议
点赞
收藏

51CTO技术栈公众号