继承类
使用extends关键字来继承一个类。如果将类声明为final的,则这个类不能被继承。如果将类的方法和字段声明为final,则它们不能被重写。
重写方法
在Scala中重写一个非抽象方法必须使用override修饰符。调用超类的方法就如Java一样,使用super关键字。
类型检查和转换
使用isInstanceOf方法来检测某个对象是否为某个特定的类;如果检测通过,则可以使用asInstanceOf方法来将对象转换为子类。
如果p是null,p.isInstanceOf[Employee]将会返回false;如果p不是Employee,则会抛出一个异常。
如果说需要检查p是一个Employee而且不是其子类,则如下使用:
还有个更好的选择,使用模式匹配:
protected字段和方法
用protected修饰符声明的字段和方法,可以被子类访问,但不能从其他位置访问。要注意,protected成员在当前类所属的包来说,也是不可见的,这是与Java不同的。
Scala提供了与private[this]类似的protected[this]。
超类的构造
在学习构造器时可以知道,辅助构造器最终都会调用主构造器。在Scala中,只有主构造器才能主动调用超类的构造器。
主构造器是与类的定义混合在一起的,调用超类构造器也是与类的定义交织在一起的。
重写字段
因为Scala的字段是由私有字段和setter/getter共同组成的,所以在重写的时候,对于不同类型的声明会有不同的限制。
声明的类型有val、var和def。限制:
重写val |
|
错误 | 错误 |
重写def |
|
和Java一样 | 重写getter/setter,只重写getter报错 |
重写var | 错误 | 错误 | 仅当超类的var是抽象的才可以 |
从这里看来,使用var是个很不好的选择。不过我暂时还不知道有什么样更好的方案。
匿名子类
从技术上讲,这会创建出一个结构类型的对象。结构类型要到后面才能细说。类型标记为
。可以将这个类型作为参数类型的定义:
抽象类
用abstract关键字来标记不能被实例化的类。如果某个类存在抽象方法,该类就必须是abstract的。
但抽象方法不需要使用abstract关键字,只要将方法体留为空即可。
重写超类的抽象方法时,不需要使用override关键字。
抽象字段
没有初始值的字段即是抽象字段。根据是val声明还是var声明,会生成相应的抽象的setter/getter。但是不生成字段。
查看编译后的字节码,可以得知,JVM类只生成了setter/getter,但没有生成字段。
构造顺序和提前定义(L3)
这个主题好高的技能等级…不过看下来也挺好理解。这个等级说明的是要求等级,而不是难度等级。
现有如下的类:
在构造时,发生的过程如下:
- Ant构造器在构造自己之前,调用超类构造器;
- Creature的构造器将range字段设为10;
- Creature的构造器初始化env数组,调用range字段的getter;
- range的getter被Ant类重写了,返回的Ant类中的range,但是Ant类还未初始化,所以返回了0;
- env被设置成长度为0的数组
- Ant构造器继续执行,将range字段设为2。
在Java中也会出现碰见相似的问题,被调用的方法被子类所重写,有可能结果不是预期的。在构造器中,不应该依赖val的值。(只能重写超类抽象的var声明字段,所以没有这个问题;如果是def,也一样会出现这种问题。)
这个问题的根本原因来自于Java语言的设计决定——允许在超类的构造方法中调用子类的方法。而在C++中,构造前后会更改指向虚函数的指针,所以不会出现这类问题。
这个问题有几种解决方法:
- 将val声明为final,安全但不灵活;
- 在超类中将val声明为lazy,安全但不高效;
- 使用提前定义语法。
提前定义语法真的如书上所说——难看到家了,估计没人会喜欢。将需要提前定义的成员放在extends关键字后的一个语法块中,还需要使用with关键字:
提前定义的等号右侧只能引用之前已经有的提前定义,不能出现类中其他的成员(因为都还没初始化呢)。
Tip:
使用-Xcheckinit编译器标志来调试构造顺序问题。这个标志会在有未初始化的字段被访问时抛出异常。
Scala继承层级
这个还是搭配图来看比较好,这里贴的是《Programming in Scala》一书的图。
与Java中基本类型对应的类,以及Unit类,都继承自AnyVal。所有其他的类都继承自AnyRef,AnyRef相当于Java中的Object类。
AnyVal和AnyRef都继承自Any类,Any类是整个层级的根节点。Any类定义了isInstanceOf、asInstanceOf方法,以及用于相等性判断和哈希码的方法。
AnyVal没有添加任何方法,只是所有值类型的一个标记。AnyRef追加了来自Object类的监视方法wait和notify/notifyAll,同时提供了一个带函数参数的方法synchronized,等同于Java中的synchronized块。
所有Scala类都实现ScalaObject这个特质,这个特质没有定义任何方法。(ScalaObject在2.10.0版本后被移除了。)
在层级的另一端,Null是所有AnyRef类型的子类型;Nothing是所有类型的子类型。
Null类的唯一实例是null值。可以将null赋值给引用类型,但不能赋值给值类型。Nothing类型没有实例,但对泛型结构时常有用。比如,空列表Nil的类型是List[Nothing],是List[T]的子类型。
Noting类型与其他语言中出现的void是没有关系的。Scala中void由Unit类型表示,Unit类型只有一个值,( )。虽然Unit不是其他类型的超类,但是编译器允许任何值被体换成( )。
对象相等性(L1)
AnyRef的eq方法会检查两个引用是否指向同一个对象。而AnyRef的equals方法默认是调用eq方法的,也就是说,equals默认实现是检查两个引用是否是同一个对象。如果需要其他的相等性判断,就需要重写equals方法。
当定义equals时,也需要同时重写hashCode方法。计算哈希码时,应该只使用用来做相等性判断的字段来进行。
在应用程序当中,通常不直接调用eq或equals方法,使用==操作符就好了。对于引用类型来说,==操作符会在做完必要的null检查之后调用equals方法。
本章习题参考。只能作为小小的参考。
4.
相关推荐
在Scala中结合使用Spring Boot的基本指南 将JDK版本更新为1.8,以使用Lambda 动作可以返回rx.Observable,就像返回Callable或DeferredResult一样,请参见RxJavaController 当控制器返回Callable / DeferredResult ...
第14讲-Scala编程详解:面向对象编程之继承 共13页 第15讲-Scala编程详解:面向对象编程之Trait 共14页 第16讲-Scala编程详解:函数式编程 共14页 第17讲-Scala编程详解:函数式编程之集合操作 共9页 第18讲-Scala...
第14讲-Scala编程详解:面向对象编程之继承 共13页 第15讲-Scala编程详解:面向对象编程之Trait 共14页 第16讲-Scala编程详解:函数式编程 共14页 第17讲-Scala编程详解:函数式编程之集合操作 共9页 第18讲-Scala...
第14讲-Scala编程详解:面向对象编程之继承 共13页 第15讲-Scala编程详解:面向对象编程之Trait 共14页 第16讲-Scala编程详解:函数式编程 共14页 第17讲-Scala编程详解:函数式编程之集合操作 共9页 第18讲-Scala...
第14讲-Scala编程详解:面向对象编程之继承 共13页 第15讲-Scala编程详解:面向对象编程之Trait 共14页 第16讲-Scala编程详解:函数式编程 共14页 第17讲-Scala编程详解:函数式编程之集合操作 共9页 第18讲-Scala...
第14讲-Scala编程详解:面向对象编程之继承 共13页 第15讲-Scala编程详解:面向对象编程之Trait 共14页 第16讲-Scala编程详解:函数式编程 共14页 第17讲-Scala编程详解:函数式编程之集合操作 共9页 第18讲-Scala...
第14讲-Scala编程详解:面向对象编程之继承 共13页 第15讲-Scala编程详解:面向对象编程之Trait 共14页 第16讲-Scala编程详解:函数式编程 共14页 第17讲-Scala编程详解:函数式编程之集合操作 共9页 第18讲-Scala...
第14讲-Scala编程详解:面向对象编程之继承 共13页 第15讲-Scala编程详解:面向对象编程之Trait 共14页 第16讲-Scala编程详解:函数式编程 共14页 第17讲-Scala编程详解:函数式编程之集合操作 共9页 第18讲-Scala...
第14讲-Scala编程详解:面向对象编程之继承 共13页 第15讲-Scala编程详解:面向对象编程之Trait 共14页 第16讲-Scala编程详解:函数式编程 共14页 第17讲-Scala编程详解:函数式编程之集合操作 共9页 第18讲-Scala...
scala语言是支持面向对象编程的,我们也可以使用scala来实现继承,通过继承来减少重复代码。 定义语法 scala和Java一样,使用extends关键字来实现继承 可以在子类中定义父类中没有的字段和方法,或者重写父类的方法 ...
一门非常好的课程涵盖了 Scala 基础、函数、递归、不可变对象、继承、类型和模式匹配、列表、集合和组合搜索以及惰性求值。 Martin Odersky、Erik Meijer 和 Roland Kuhn 教授。 以下课程涵盖函数式编程和可变状态...
快学Scala课后习题答案,包含各个章节答案word版和pdf版
Scala继承和特质.md
它一方面吸收继承了多种语言中的优秀特性,一方面又没有抛弃 Java 这个强大的平台,它运行在 Java 虚拟机 (Java Virtual Machine) 之上,轻松实现和丰富的 Java 类库互联互通。它既支持面向对象的编程方式,又支持...
继承与覆盖(override) 18 特质(trait) 19 显式类型转换 20 隐式转换、隐式参数 20 类型参数化 21 类型信息 22 集合 23 异常 27 断言、检查 27 包和引用 27 scala I/O 29 Actor和并发 29 GUI编程 31 结合scala和java ...
第1章 零到六十:Scala简介 1 1.1 为什么选择Scala 1 1.1.1 富有魅力的Scala 2 1.1.2 关于Java 8 3 1.2 安装Scala 3 1.2.1 使用SBT 5 1.2.2 执行Scala命令行工具 6 1.2.3 在IDE中运行Scala ...
面向对象编程 – 继承 复用 ~ 可扩展性 ~ 可维护性 extends 使用 extends 关键字表示继承。 继承就代表,子类可以从父类继承父类的 field 和 method 。...在 Scala 中,如果子类要覆盖一个父类中非抽象方法,则必须使用
02.Scala程序和Java程序对比 03.Scala环境搭建 04.Scala解释器 05.案例_做最好的自己 第二章 变量和数据类型 00.导学 01.输出语句和分号 02.Scala中的常量 03.Scala中的变量 04.字符串的定义 05.惰性赋值 06.标识符 ...