Scala 语言通过 extends 关键字来继承类.
那么继承一个类有什么好处呢? 子类除了拥有继承自超类的方法和字段 (即为 val(常量), var(变量) 所定义的), 还可以添加自己需要的新方法和新字段, 而且不但可以重写 (override) 超类的方法, 还可以重写超类的
.
- 字段
在 Scala 中, 不仅可以将类声明为 final, 而且可以将字段和方法声明为 final
当类被声明为 final 时, 类不可以被继承; 当方法和字段被声明为 final 时, 对应的方法和字段不可以被子类重写, 看看下面这个例子就一目了然
- class Person {
- final val key = 0 val e = 1
- }
- class Kid extends Person {
- // 报错: Value 'key' can not override final member
- // override val key = 1
- override val e = 2
- }
- object test extends App {
- val k = new Kid;
- println(k.key) println(k.e)
- }
- /*output
- 0
- 2
- */
在 Scala 中重写一个非抽象方法
使用
- 必须
修饰符, 如:
- override
- override def toString: String = getClass.getName + "[name=" + name + "]"
override 修饰符可以在多个常见的情况下给出有用的错误提示, 包括:
Scala 语言使用
关键字调用超类的方法, super.toString 相当于 Person.toString
- super
- class Person {
- final val key = 0 val name = "person"val age = 1
- override def toString: String = getClass.getName + "[name=" + name + "]"
- }
- class Kid extends Person {
- //override val key = 1
- override val name = "kid"override val age = 2
- override def toString: String = super.toString + "[age=" + age + "]"
- }
- object test extends App {
- val k = new Kid;
- println(k.key) println(k.age) println(k)
- }
- /*output
- 0
- 2
- chap08.Kid[name=kid][age=2]
- */
Scala 语言中可以使用 isInstanceOf[T] 方法, 测试某个对象实际类型是否属于某个给定类 T 或者类 T 的子类; 测试成功之后可以用 asInstanceOf[T] 方法将对象引用转化为的 (子类) 类 T 引用(一般来说对象的引用类型是 T 的父类, 而实际类型是 T 或者 T 的子类)
- if (kid.isInstanceOf[Kid]) {
- val s = kid.asInstanceOf[Kid]
- }
如果 kid 是 null, 则 kid.isInstanceOf[Kid] 返回 false, kid.asInstanceOf[Kid] 返回 null, 如果 kid 不是一个 Kid, kid.asInstanceOf[Kid] 将抛出异常
如果要测试 kid 指向 Kid 类又不是其子类, 使用如下方法:
- if (kid.getClass == classOf[Kid]) {
- val s = kid.asInstanceOf[Kid]
- }
类有一个主构造器和任意数量的辅助构造器, 而每个辅助构造器都必须以对先前定义的辅助构造器或者主构造器的调用开始, 这样做的结果就是:
辅助构造器
直接调用超类的构造器; 子类的辅助构造器最终都会调用主构造器; 只有主构造器而已调用超类的构造器.
- 永远都不可能
主构造器是和类的定义交织在一起, 调用超类的构造器同样也交织在一起
- class Kid(gender: String, val height: Double) extends Person(gender)
Kid 类有 2 个参数, 一个被 "传递" 到超类
scala 语言的 (主) 构造器中, 你不能调用 super(paras)
Scala 的字段 (Fields) 由一个私有字段和取值器 / 改值器方法构成
你可以用一个同名的 val 字段重写一个 val 或者不带参数的 def, 子类有一个私有字段和一个共有的 getter 方法, 而这个 getter 方法重写了超类的 getter 方法.
- class Smiler(val happy: String) {
- override def toString: String = getClass.getName + "[happy: " + happy + "]"
- }
- class Laughter(veryhappy: String) extends Smiler(veryhappy) {
- override val happy: String = "Laughter"override val toString: String = super.toString
- }
更常见的例子是 val 重写抽象的 def, 就像这样:
- abstract class Smiler(val happy: String) {
- def degree: Int
- }
- class Laughter(lhappy: String, override val degree: Int) extends Smiler(lhappy) {}
注意如下限制:
你可以通过包含带有定义或重写的代码块的方式创建一个匿名子类, 比如
- val alien = new Person("good") {
- def greeting = "hi, good"
- }
关键字
- override
Scala 中使用 abstract 关键字来标记不能实例化的类, 通常是因为它的某个或者几个方法没有完整定义. 例如
- abstract class Smiler(val happy: String) {
- def degree: Int
- }
- class Laughter(lhappy: String) extends Smiler(lhappy) {
- def degree = lhappy.hashCode
- }
除了抽象方法外, 类还可以有抽象字段; 抽象字段就是一个没有初始值的字段. 具体的子类必须提供具体的字段; 和方法一样, 子类中重写超类的抽象字段时, 不需要
关键字
- override
- abstract class Abstract {
- val id: Int // 没有初始化, 这是一个带有getter方法的抽象字段
- var name: String // 没有初始化, 这是一个带有getter和setting方法的抽象字段
- }
- class AbstractField(val id: Int) extends Abstract {
- var name = getClass.getName // override 可选
- }
可以随时用匿名类型来定制抽象字段
- val laught = new Abstract {
- val id = 10
- var name = "laught"
- }

- AnyVal
是 List[Nothing], 它是 List[T] 的子类型, T 可以是任何类型
- Nil
Scala 中的 Nothing 类型和 Java 中 void 不是一个概念;
Scala 中 void 由 Unit 类型表示, 该类型只有一个值, 那就是 ();
虽然 Unit 不是任何类型的超类, 但编译器允许任何值来替换成 ();def printAny(x: Any) {print(x)}
def printUnit(x: Unit) {print(x)}
printAny("happy")
printUnit("happy")
Scala 中调用
, 如果比较的是引用类型, Scala 会先做
- ==
检查, 然后调用
- null
方法
- equals
来源: http://www.cnblogs.com/nowgood/p/scalainherit.html