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

1. 与Java基本类型相对应的类以及Unit类型(相当于Java的void)都扩展自`AnyVal`
2. 所有其他类都是AnyRef的子类, Any是整个继承层级的根节点, AnyVal和AnyRef扩展自Any类
3. Any类定义了isInstanceOf asInstanceOf方法, 以及用于相等性判断和哈希码方法, AnyVal并没有追加方法, 只是所有值类型的一个标记
4. Null类型唯一的实例就是null, 你可以将null赋值给任何引用, 但不能赋值给值类型的变量, 举例来说不能讲Int赋值为null
5. Nothing类型没有实例, 它对于泛型结构很有用, 比如说空列表`Nil`是List[Nothing], 它是List[T]的子类型, T可以是任何类型
> Scala中的Nothing类型和Java中void不是一个概念;
> Scala中void由Unit类型表示, 该类型只有一个值, 那就是();
> 虽然Unit不是任何类型的超类, 但编译器允许任何值来替换成();
>
> def printAny(x: Any) {print(x)}
> def printUnit(x: Unit) {print(x)}
> printAny("happy")
> printUnit("happy")
## 9. 对象相等性
Scala中调用 `==`, 如果比较的是引用类型, Scala会先做`null`检查, 然后调用`equals` 方法
快学Scala之继承的更多相关文章
- 《快学Scala》
Robert Peng's Blog - https://mr-dai.github.io/ <快学Scala>Intro与第1章 - https://mr-dai.github.io/S ...
- 快学Scala 第十九课 (trait的abstract override使用)
trait的abstract override使用: 当我看到abstract override介绍的时候也是一脸懵逼,因为快学scala,只介绍了因为TimestampLogger中调用的super ...
- 快学Scala习题解答—第一章 基础
1 简介 近期对Scala比较感兴趣,买了本<快学Scala>,感觉不错.比<Programming Scala:Tackle Multi-Core Complexity on th ...
- 快学Scala 第十一课 (类继承)
类继承: class People { } class Emp extends People{ } 和Java一样,final的类不能被继承.final的字段和方法不能被override. 在Scal ...
- 快学Scala 第十八课 (trait多继承)
trait多继承: trait的继承并不像类拥有相同的含义!在下面这个例子中,如果还是运用类的继承的思想,那么运行结果将是什么也没有. trait Logged { def log(msg: Stri ...
- 《快学Scala》第八章 继承
- [Scala] 快学Scala A1L1
基础 1.1 声明值和变量 在Scala中,鼓励使用val; 不需要给出值或变量的类型,这个信息可以从初始化表达式推断出来.在必要的时候,可以指定类型. 在Scala中,仅当同一行代码中存在多条语句时 ...
- 快学Scala-第八章 继承
知识点: 1.扩展类 extends关键字,在定义中给出子类需要而超类没有的字段和方法,或者重写超类的方法. 2.重写方法 在Scala中重写一个非抽象方法必须 override 修饰符 public ...
- 《快学Scala》——控制结构和函数
条件表达式 在Scala中if/else表达式有值,这个值就是跟在if或else之后的表达式的值.例如: if (x > 0) 1 else -1 上述表达式的值是1或-1,具体是哪一个取决于x ...
随机推荐
- MySQL主从同步报错故障处理集锦
前言 在发生故障切换后,经常遇到的问题就是同步报错,下面是最近收集的报错信息. 记录删除失败 在master上删除一条记录,而slave上找不到 Last_SQL_Error: Could not e ...
- ORACLE聚合函数细节
select * from emp order by mgr; 概要 select count(1), --14 sum(1), --14 count(*), --14 count(distinct ...
- Ajax请求汇总(一)
刚开始结束Ajax请求的时候,那真的是迷迷糊糊,昏天暗地,通过学习的深入和翻阅各种资料.求助度娘,总结一下Ajax请求,与大家分享一下,希望能给学习Ajax的同学一些帮助,废话不多手,直接开始~~~ ...
- python 第五弹
*:first-child { margin-top: 0 !important; } .markdown-body>*:last-child { margin-bottom: 0 !impor ...
- linux下部署php项目-Apache、php、mysql关联
linux下部署php项目环境可以分为两种,一种使用Apache,php,mysql的压缩包安装,一种用yum命令进行安装. 使用三种软件的压缩包进行安装,需要手动配置三者之间的关系.apache和p ...
- 使用DotNetty编写跨平台网络通信程序
长久以来,.Net开发人员都非常羡慕Java有Netty这样,高效,稳定又易用的网络通信基础框架.终于微软的Azure团队,使用C#实现的Netty的版本发布.不但使用了C#和.Net平台的技术特点, ...
- Eclipse导入项目常见问题----facet版本问题04
问题如下: 解决办法 右击项目,找到最下面的properties,在搜索facet jdk版本问题(有个红色感叹号)01:http://blog.csdn.net/baidu_37107022/art ...
- 在.NET Core中使用Irony实现自己的查询语言语法解析器
在之前<在ASP.NET Core中使用Apworks快速开发数据服务>一文的评论部分,.NET大神张善友为我提了个建议,可以使用Compile As a Service的Roslyn为语 ...
- window maven批量删除.lastUpdated文件
当下载网络上的jar包 网络不通 中途中断 会产生.lastUpdated,maven就不在从网上下载jar包了 很烦 ~~~ 执行下面的批处理程序即可 @echo off set REPOSITOR ...
- Ajax&jQuery教案总结
Ajax&jQuery教程总结 目录 第一章 Ajax入门 6 第1讲 传统表单提交存在的问题 6 课程内容 6 1. 问题的引入 6 2. 问题的解决 6 参考进度(0.5课时) 7 第2讲 ...