Scala中的override

override是覆盖的意思,在很多语言中都有,在scala中,override是非常常见的,在类继承方面,它和java不一样,不是可写可不写的了,而是必须写的。如果不写而覆盖了对应的属性或者方法的话,编译器就会报错了。今天把scala中的override的各种地方都整理了一遍,以方便以后翻阅。

基础用法

/*
基本的override特性
*/
class A {
val nameVal = "A"
var nameVar = "A" def foo: String = {
"A.foo"
}
} class B extends A {
override val nameVal = "B"
//override var nameVar = "B" "variable nameVar cannot override a mutable variable"
override def foo: String = {
"B.foo"
}
} val b1 = new B
b1.foo
b1.nameVal
b1.nameVar val b2 : A = new B
b2.foo
b2.nameVal
b2.nameVar = "B"
b2.nameVar 输出: defined class A defined class B b1: B = B@9825fab
res0: String = B.foo
res1: String = B
res2: String = A b2: A = B@c46c4a1
res3: String = B.foo
res4: String = B
b2.nameVar: String = B
res5: String = B

当一个类extends另外一个类的时候,override的规则基本如下:

  • 子类中的方法要覆盖父类中的方法,必须写override(参见foo)
  • 子类中的属性val要覆盖父类中的属性,必须写override(参见nameVal)
  • 父类中的变量不可以覆盖(参见nameVar)

在抽象类中可以不用写override

/*
trait的extent不需要override
*/
trait T {
def foo : String
def bar : String
} class TB extends T {
def foo: String = {
"TB.foo"
} def bar: String = "TB.bar"
} val tb = new TB
tb.foo
tb.bar trait TT extends T {
def bar :String = "TT.bar"
} class TTB extends TT {
def foo: String = "TTB.foo"
}
val ttb = new TTB
ttb.foo
ttb.bar 输出: defined trait T defined class TB tb: TB = TB@2fb497ea
res6: String = TB.foo
res7: String = TB.bar defined trait TT defined class TTB ttb: TTB = TTB@346c06af
res8: String = TTB.foo
res9: String = TT.bar

T是特性类,它定义了两个抽象方法,foo和bar。TB的类继承和实现了T特性类,这个时候,TB类中的foo和bar前面的override是可写可不写的。这里初步看下TB类中的foo和bar前面的override写和不写感觉都一样,但是一旦有钻石结构的类继承,这个override的作用就体现出来了。这个我们后续说。

TT和TTB的例子也是说明了下trait继承trait是不需要使用override的。

abstrct class 也不需要使用override

/*
abstrct class 不需要override
*/
abstract class PA(name: String) {
def hello: String
} class PB(name: String) extends PA(name) {
def hello : String = s"hello ${name}"
} val pb = new PB("yejianfeng")
pb.hello 输出: defined class PA defined class PB pb: PB = PB@62840167
res10: String = hello yejianfeng abstract class和trait的特性主要是在是否有构造参数,在override方面都是一样的。

钻石结构

所谓的钻石结构就是一个菱形的结构,一个基类,两个子类,最后一个类又继承这两个子类。那么如果这两个子类都包含一个基类的方法,那么最后的这个类也有这个方法,选择继承那个子类呢?

/*
钻石结构
*/
trait Animal {
def talk: String
} trait Cat extends Animal {
def talk: String = "I am Cat"
} trait Monkey extends Animal {
def talk: String = "I am monkey"
} trait Dog extends Animal {
override def talk: String = "I am Dog"
} val kittyDog = new Cat with Dog
kittyDog.talk class MonkeyCat extends Monkey with Cat {
override def talk: String = "I am monkeyCat"
} val monkeyCat = new MonkeyCat
monkeyCat.talk 输出: defined trait Animal defined trait Cat defined trait Monkey defined trait Dog kittyDog: Cat with Dog = $anon$1@5378ef6d
res11: String = I am Dog defined class MonkeyCat monkeyCat: MonkeyCat = MonkeyCat@1e444ce6
res12: String = I am monkeyCat

在这个例子中,Animal是基类,Cat和Dog是子类,kittyDog是继承了Cat和Dog,那么kittyDog里面的talk使用的是Cat和Dog中有标示override的那个方法。这个时候override的作用就体现出来了。

参数复写使用override

我们可以直接在构造函数里面使用override重写父类中的一个属性。我理解这个更多是语法糖的一个功能。

/*
参数复写
*/
class Person(val age : Int){
val name = "no name"
} class XiaoMing(age: Int, override val name: String) extends Person(age){ }
val xiaoming = new XiaoMing(12, "xiaoming")
xiaoming.name 输出:
defined class Person defined class XiaoMing xiaoming: XiaoMing = XiaoMing@2eef0f3c
res13: String = xiaoming

总结

scala中的override基本是强制性的。这个我比较赞同,这样就减少了思维逻辑的负担,看到一个类中的一个方法的时候,就明白了这个方法是否是覆写父类的方法。但是感觉由于scala类的继承的灵活性,比如钻石结构里面,要知道最终的类使用的方法是什么,就需要了解每个父类的情况,这个还是有点纠结的。

Scala中的override的更多相关文章

  1. 第2节 Scala中面向对象编程:7、继承的概念以及override和super关键字;8、isInstanceOf 和 asInstanceOf关键字

    6.3.   Scala面向对象编程之继承 6.3.1.     Scala中继承(extends)的概念 Scala 中,让子类继承父类,与 Java 一样,也是使用 extends 关键字: 继承 ...

  2. scala中的面向对象定义类,构造函数,继承

    我们知道scala中一切皆为对象,函数也是对象,数字也是对象,它是一个比java还要面向对象的语言. 定义scala的简单类 class Point (val x:Int, val y:Int) 上面 ...

  3. scala入门教程:scala中的面向对象定义类,构造函数,继承

    我们知道scala中一切皆为对象,函数也是对象,数字也是对象,它是一个比java还要面向对象的语言. 定义scala的简单类 class Point (val x:Int, val y:Int) 上面 ...

  4. scala中的抽象类

    scala中也有和java,c#类似的抽象类,抽象类会有部分实现,也有没有实现的方法定义.抽象类最大的特征是不能直接实例化.下面我们看个例子. abstract class Animal { def ...

  5. Scala 中 构造函数,重载函数的执行顺序

    在调试scala在线开发教程(http://www.imobilebbs.com/wordpress/archives/4911)的过程中看到了以下代码,但是这段代码无论怎么调试都无法成功. abst ...

  6. Scala 深入浅出实战经典 第57讲:Scala中Dependency Injection实战详解

    王家林亲授<DT大数据梦工厂>大数据实战视频 Scala 深入浅出实战经典(1-87讲)完整视频.PPT.代码下载:百度云盘:http://pan.baidu.com/s/1c0noOt6 ...

  7. Scala 中的函数式编程基础(三)

    主要来自 Scala 语言发明人 Martin Odersky 教授的 Coursera 课程 <Functional Programming Principles in Scala>. ...

  8. scala中的Type使用

    trait Base { val name: String } case class S( name: String, age: Int ) extends Base case class F( na ...

  9. Programming In Scala笔记-第十一章、Scala中的类继承关系

    本章主要从整体层面了解Scala中的类层级关系. 一.Scala的类层级 在Java中Object类是所有类的最终父类,其他所有类都直接或间接的继承了Object类.在Scala中所有类的最终父类为A ...

随机推荐

  1. Bluetooth Obex

    OPP 1.2 which uses OBEX over L2CAP. OPP 1.1 connection and transfer happens over RFCOMM->L2CAP.

  2. Java基础笔记1

    java (开源,跨操作系统)j2ee jre java基础 javaoop java高级 JDK(JAVA developer Kitool): java开发工具 (开发人员使用) JRE(java ...

  3. 笔记-java泛型详解

    首先,先说明一下,java泛型文章的出处:http://www.cnblogs.com/lzq198754/p/5780426.html 作为学习笔记保存. 1.为什么需要泛型 泛型在Java中有很重 ...

  4. 爆炸快求1~n有多少素数

    这个求一千亿以内的素数大约用6780ms #include <stdio.h> #include <iostream> #include <string.h> #i ...

  5. 路由知识 静态路由 rip eigrp ospf

    第1章 路由选择原理 1.1 几个概念 1.1.1 被动路由协议 用来在路由之间传递用户信息 1.1.2 主动路由协议 用于维护路由器的路由表 R2#show ip route Codes: C - ...

  6. JDBC(MySQL)一周学习总结(一)

    一周过去了,我在这分享一下这一周来学习 JDBC 的知识,同时也希望可以帮到别人! 首先我们从获取 JDBC 连接开始 Driver(每个驱动程序类必须实现的接口) 获取数据库连接需要配置数据库连接信 ...

  7. Grunt打包之seajs项目【转】

    原文:http://www.cnblogs.com/accordion/p/4508154.html grunt与seajs grunt是前端流行的自定义任务的脚手架工具,我们可以使用grunt来为我 ...

  8. HTML学习笔记 基础标签及css引用案例 第一节 (原创)参考使用表

    <!DOCTYPE html><!--头文件 不是标签 也没有结束,这是声明该文件为HTML5--><html lang="en"><!- ...

  9. Oracle 11g服务器安装详细步骤——图文教程

    1.大家可以根据自己的操作系统是多少位(32位或64位)的,到官网下载相应的安装程序,如下图所示. 有一点需要注意,Oracle的安装程序分成2个文件,下载后将2个文件解压到同一目录即可. 2.下载完 ...

  10. C++使用htslib库读入和写出bam文件

      有时候我们需要使用C++处理bam文件,比如取出read1或者read2等符合特定条件的序列,根据cigar值对序列指定位置的碱基进行统计或者对序列进行处理并输出等,这时我们可以使用htslib库 ...