Scala 的继承体系很有意思,
Any
是所有类的超类,Nothing
是所有类的子类
Scala的类层次(Hierarchy)
Any 类的大纲如下所示:
final def ==(that: Any): Boolean
final def !=(that: Any): Boolean
def equals(that: Any): Boolean
def ##: Int
def hashCode: Int
def toString: String
注意上述类中的
final
修饰符
==
操作符在 Scala 中是比较操作元的内容,而非引用,如果要比较引用,需要使用eq
ornq
AnyVal 是所有值类的父类,AnyRef是所有引用类的父类。值类就是可以在类中直接以字面量来表示的类,你不能使用new
关键字来创建值类,且值类是不能被继承的,因为 Scala 将值类定义为抽象的且是final
的
Unit
是一个单实例的值,被写作()
底类型(Bottom types)
从类的层次图上面来看,Scala 有两个底类型
Null
,Nothing
Null 是 null 的引用,它是所有引用类(reference class)的子类,Null 和值类型是不兼容的,所以不能这样做
val one: Int = null // 编译不通过
Noting 是 Scala 类层次的最低端,是所有类的子类型。Nothing 的一个用途就是标识异常的终止(signals abnormal termination)
val result: String = if (true) "OK" else throw new RuntimeException
避免单一化类型(Avoiding a types monocultrue)
在 Scala 中,要充分利用编译的功能,不要使用单一化的类,应该将类拆的尽可能小(tiny type),让编译器在编译期为你发现很多的手误
何为单一化类型,比如一个类的参数,全部使用字符串来进行表示,就特别容易造成在构造该类的时候,参数传递的顺序乱掉了,编译器依然能够编译通过;如果将参数使用类来定义,就可以避免如此问题。如下
class Foo(header: String, body: String, footer: String)
// 编译器不会帮你发现错误
val foo = new Foo("body", "header", "footer") // wrong order
// difining tiny class
class Header
class Body
class Footer
class Foo(header: Header, body: Body, footer: Footer)
val foo = new Foo(new Header, new Body, new Footer)
// 编译器会帮你发现错误
val foo4Wrong = new Foo(new Body, new Header, new Footer)