Scala 继承
1. 继承
Scala 通过 extends 关键字来继承类.
那么继承一个类有什么好处呢?
- 子类拥有继承自超类的方法和字段(即为val(常量), var(变量)所定义的)
- 可以添加自己需要的新方法和新字段,
- 不但可以重写超类的方法, 还可以重写超类的字段.
final 关键字
Scala 中, 不仅可以将类声明为 final, 而且可以将字段和方法声明为 final
当类被声明为 final 时, 类不可以被继承; 当方法和字段被声明为 final 时, 对应的方法和字段不可以被子类重写, 看看下面这个例子就一目了然
class Person {
final val name = "person"
val age = 1
}
class Kid extends Person {
// 报错: Value 'name' can not override final member
// override val name = "jerry"
override val age = 2
}
object test extends App {
val k = new Kid;
println(k.age) // 2
}
2. 重写方法
在 Scala 中重写一个 非抽象方法
必须使用 override 修饰符, 如:
override def toString: String = getClass.getName + "[name=" + name + "]"
override修饰符可以在多个常见的情况下给出有用的错误提示, 包括:
- 当你拼错了要重写的方法名和字段名
- 当你不小心在新方法中使用了错误的参数类型
- 当你在超类中引入了新方法, 而这个新方法和子类的方法抵触
Scala 使用 super 关键字调用超类的方法, super.toString 相当于 Person.toString
class Person {
val name = "person"
val age = 1
override def toString: String = getClass.getName + "[name=" + name + "]"
}
class Kid extends Person {
override val name = "kid"
override val age = 2
override def toString: String = super.toString + "[age=" + age + "]"
}
object test extends App {
val person = new Kid;
println(person.age) // 2
println(person) // chap08.Kid[name=kid][age=2]
}
3. 类型检查和转换
Scala语言中可以使用 isInstanceOf[T] 方法, 测试某个对象实际类型是否属于某个给定类T或者类T的子类; 测试成功之后可以用 asInstanceOf[T] 方法将对象引用转化为的(子类)类T引用(一般来说对象的引用类型是T的父类, 而实际类型是T或者T的子类)
if (person.isInstanceOf[Kid]) {
val k = person.asInstanceOf[Kid]
}
如果 person 是null, 则 person.isInstanceOf[Kid] 返回false, kid.asInstanceOf[Kid] 返回null;
如果 person 不是一个 Kid, kid.asInstanceOf[Kid]将抛出异常
如果要测试 person 指向Kid类又不是其子类, 使用如下方法:
if (person.getClass == classOf[Kid]) {
val s = person.asInstanceOf[Kid]
}
4. 超类构造
类有一个主构造器和任意数量的辅助构造器, 而每个辅助构造器都必须以对先前定义的辅助构造器或者主构造器的调用开始, 这样做的结果就是:
辅助构造器永远都不可能
直接调用超类的构造器; 子类的辅助构造器最终都会调用主构造器; 只有主构造器而已调用超类的构造器.
主构造器是和类的定义交织在一起, 调用超类的构造器同样也交织在一起
class Kid(gender: String, val height: Double) extends Person(gender)
Kid类有2个参数, 一个被"传递"到超类
scala语言的(主)构造器中, 你不能调用super(paras)
5. 重写字段
Scala 的字段(Fields)是指 一个 var或者val 定义的变量(或值)和对应的getter/setter 方法
你可以用一个同名的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(h: String, override val degree: Int) extends Smiler(h) {
}
注意如下限制:
- def 只能重写另一个def
- val 只能重写另一个val或者不带参数的def
- var 只能重写另一个抽象的var
6. 匿名子类
你可以通过包含带有定义或重写的代码块的方式创建一个匿名子类,比如
val alien = new Person("good") {
def greeting = "hi, good"
}
7. 抽象类与抽象字段
- 不需要对抽象方法和抽象字段用 abstract 关键字
- 子类中重写超类的抽象方法和抽象字段时, 可以不写 override 关键字, 不过 scala in depth 一书分析了总是使用 override 关键字会带来更多的好处, 那就加上吧
- 只要类中存在抽象方法, 该类必须声明为 abstract
7.1 抽象类
Scala 中使用 abstract 关键字来标记不能实例化的类, 通常是因为它的某个或者几个方法没有完整定义. 例如
abstract class Smiler(val happy: String) {
def degree: Int
}
- 在Scala中, 不需要对抽象方法用 abstract 关键字, 只是省去其方法体
- 只要类中存在抽象方法, 该类必须声明为 abstract
- 子类重写超类的抽象方法时, 不需要 override 关键字
class Laughter(h: String) extends Smiler(h) {
def degree = h.hashCode
}
7.2 抽象字段
除了抽象方法外, 类还可以有抽象字段; 抽象字段就是一个没有初始值的字段. 具体的子类必须提供具体的字段; 和方法一样, 子类中重写超类的抽象字段时, 不需要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"
}
8. Scala继承层级
- 与Java基本类型相对应的类以及Unit类型(相当于Java的void)都扩展自
AnyVal
- 所有其他类都是AnyRef的子类, Any是整个继承层级的根节点, AnyVal和AnyRef扩展自Any类
- Any类定义了isInstanceOf asInstanceOf方法, 以及用于相等性判断和哈希码方法, AnyVal并没有追加方法, 只是所有值类型的一个标记
- Null类型唯一的实例就是null, 你可以将null赋值给任何引用, 但不能赋值给值类型的变量, 举例来说不能讲Int赋值为null
- Nothing类型没有实例, 它对于泛型结构很有用, 比如说空列表
Nil
是List[Nothing], 它是List[T]的子类型, T可以是任何类型
Scala中的Nothing类型和Java中void不是一个概念;
Scala中void由Unit类型表示, 该类型只有一个值, 那就是();
<<快学Scala>> 中所说虽然Unit不是任何类型的超类, 但编译器允许任何值来替换成(), 不过现在测试scala2.12.2, Scala已经修改这个语法, 现在不管传入什么值, printUnit的输出结果都是()
def printAny(x: Any) {print(x)}
def printUnit(x: Unit) {print(x)}
printAny("happy")
printUnit("happy")
/*output:
happy
()
/*
9. 对象相等性
Scala中调用 ==
, 如果比较的是引用类型, Scala会先做null
检查, 然后调用equals
方法
Scala 继承的更多相关文章
- Scala学习(八)---Scala继承
Scala继承 摘要: 在本篇中,你将了解到Scala的继承与Java和C++最显著的不同.要点包括: 1. extends.final关键字和Java中相同 2. 重写方法时必须用override ...
- 7.scala:继承
版权申明:转载请注明出处. 文章来源:http://bigdataer.net/?p=315 排版乱?请移步原文获得更好的阅读体验 类似于java中的继承,在scala中同样有继承一说,而且在很多方面 ...
- Scala继承
override重写 为什么要用override关键字?因为这样更清楚,不容易出错,比如打错字了,就没覆盖成功,但是不会报错 override可以覆盖feild和method class Person ...
- Scala实战高手****第10课:Scala继承彻底实战和Spark源码鉴赏
isInstanceOf 和 asInstanceOf is用于判断 as用于转换,把父类类型转换成子类类型 getClass 具体找出类型
- 快学Scala之继承
## 1. 继承 Scala语言通过 extends 关键字来继承类. 那么继承一个类有什么好处呢? 子类除了拥有继承自超类的方法和字段(即为val(常量), var(变量)所定义的), 还可 ...
- Scala学习八——继承
一.本章要点 extends,final关键字和Java一样 重写方法时必须使用override 只有主构造器可以调用超类的构造器 可以重写字段 二.扩展类 Scala扩展类和Java一样(使用ext ...
- Scala 面向对象(六):面向对象的特征二:继承 (一)
1 Scala继承的基本语法 class 子类名 extends 父类名 { 类体 } class Person { var name : String = _ var age : Int = _ d ...
- [Scala] 快学Scala A1L1
基础 1.1 声明值和变量 在Scala中,鼓励使用val; 不需要给出值或变量的类型,这个信息可以从初始化表达式推断出来.在必要的时候,可以指定类型. 在Scala中,仅当同一行代码中存在多条语句时 ...
- 【Todo】【读书笔记】大数据Spark企业级实战版 & Scala学习
下了这本<大数据Spark企业级实战版>, 另外还有一本<Spark大数据处理:技术.应用与性能优化(全)> 先看前一篇. 根据书里的前言里面,对于阅读顺序的建议.先看最后的S ...
随机推荐
- Java父类与子类方法调用顺序
父类 FatherClass package 父类与子类方法调用顺序; /** * 父类 * @author shundong * */ public class FatherClass { priv ...
- RHCSA考试真题
2018年 RHCSA考试真题... ------------ 考前需要做的基础 破解root密码 KVM虚拟机与VM虚拟机 主机名:station.domain1.example.comIP地址:1 ...
- 1411 - Ants(巨人与鬼)
参考博客 紫薯P230 题意:给出平面上n个白点n个黑点,要求两两配对,且配对所连线段没有交点. 紫薯思路:找出y坐标最小的点,如果多个,考虑x最小的.将其他点相对于这个点按极角从小到大排序,然后开始 ...
- vue @blur v-model数据没有更新问题
今天遇到一个问题,是一个输入框绑定了一个失去焦点事件,要发送一个客户填写的数据给后台查询然后拿到返回值把它渲染到页面上,但是从后台获取到的数据却没有在页面上渲染出来,console.log打印时显示数 ...
- Java8中String.join方法
List names=new ArrayList<String>(); names.add("1"); names.add("2"); names. ...
- vue-router路由
Vue Router 是 Vue.js 官方的路由管理器 自动全局安装: vue create 项目名称 手动配置: 1.安装 在app项目文件夹里面 npm i vue-router 2.在min. ...
- http.lua里的装饰器
摘自:http.lua local co_yield = coroutine.yield local co_create = coroutine.create local co_status = co ...
- [ASNI C] [常用宏定义] [define技巧]
1. 打印变量名及其值 #define Inquire(var, mode) fprintf(stdout, #var" = "#mode". \n", var ...
- 关于PHP中的全局变量global和$GLOBALS的不同区分
1.global Global的作用是定义全局变量,但是这个全局变量不是应用于整个网站,而是应用于当前页面,包括include或require的所有文件. 但是在函数体内定义的global变量,函数体 ...
- (14)CountTriplets
一.问题描述 给定一个数组.三个索引 i,i ~ [0, array.length) j, j ~ [0, array.length) k, k ~ [0, array.length) 求有多少种组 ...