Scala学习笔记 A2/L1篇 - 特质Traits

教材:快学Scala

chapter 10. 特质 Traits

  • Scala特质与Java接口不同,Scala特质可以给出这些特性的缺省实现
  • class可以implement任意数量的trait
  • trait可以要求实现它们的class具备特定字段/方法/超类
  • 叠加多个trait时,排在后面的trait的方法会更优先执行

10.1 为什么没有多重继承

  • 即不允许从多个超类继承,和Java一样
  • 原因 菱形继承问题 C++的解决方案:虚基类
  • Java 没有可以实现任意数量接口 但只能包含抽象方法 不能包含字段
  • Scala trait 同时拥有抽象方法和具体方法 未被实现的方法都默认是抽象的

10.2 当接口使用的特质

class ConsoleLogger extends Logger with Cloneable with Serializable { def log(msg: String) }

  • 1个超类 >=0个特质

10.3 带具体实现的特质

  • trait可以带具体实现的方法,继承这个trait也叫做"混入"了这个trait
  • 重写具体方法时加上override关键字

10.4 带有特质的对象

  • new一个对象的时候可以加上trait
trait Logged {
    def log(msg: String) { } // 一个空的实现
}
class SavingAccount extends Account with Logged {
    def withDraw(...) {
        ...
        log("xxx") // 混入Logged的log方法 但目前还是空的实现
    }
}
trait ConsoleLogger extends Logged { 
    override def log(msg: String ) {...} // 有一个更好的实现
}

val acct = new SavingAccount with ConsoleLogger // 在具体对象中混入更好的实现,不再是空实现
val acct2 = new SavingAccount with FileLogger

10.5 叠加在一起的特质

  • 从最后一个trait开始调用
  • traitsuper.方法含义与类的super.方法不一样!!调用的是trait层级中的下一个trait。下一个意思:根据trait的with顺序决定!!
  • 也可以具体制定哪个super的方法:super[ConsoleLogger].log(...) 但只能是直接超类型

10.6 重写抽象方法

  • 问题:万一super.方法所对应的那个trait方法是抽象方法怎么办?
  • 解决方法:重写的方法加上abstract关键字
    abstract override def log(msg: String) { super.log(...) }

10.7 具体方法中调用抽象方法

  • 在同一个trait中,具体方法里可以调用抽象方法和抽象字段,在被继承的时候再混入相应的具体方法和具体字段
trait Logger {
    def log(msg: String)
    def info(msg: String) { log("INFO: " + msg) } // 具体方法里调用了抽象方法
    ...
}

10.8 特质中的字段

  • trait的字段可具体可抽象,给出初始值就是具体的
  • 实现该trait的子类,这些trait的字段是被简单加到子类中的,不是被继承的
  • 不能说是被继承的原因:一个类只能extends一个超类,因此来自trait的字段只能是作为子类的其中一个字段
  • 抽象字段必须在子类中被重写
val acct = new SavingsAccount with ConsoleLogger with ShortLogger {
    val maxLength = 20 // 在ShortLogger里的maxLength是抽象的,所以在被with的时候需要具体化
}

10.10 构造器执行顺序

  • trait构造器 与类构造器类似 由trait体语句构成
  • 构造器执行顺序:超类->左边的trait->右边的trait->子类
  • trait构造器内部执行顺序:先执行父trait构造器(多个特质共有一个父的情况只执行一次构造)
    e.g. class SavingsAccount extends Account with FileLogger with ShortLogger
    构造器执行顺序:
    Account(超类)->Logger(FileLogger的父trait)->FileLogger(最左边trait)->ShortLogger(下一个trait)->SavingsAccount(子类)

10.11 初始化抽象字段

  • trait和类的区别:trait不能有构造器参数
  • 用abstract val代替trait构造器参数
  • 陷阱:可能在初始化抽象字段时,由于构造器执行顺序问题导致空指针异常
  • 解决方法:对应用到抽象字段的val加上lazy关键字

10.12 trait extends class

  • trait可以extends trait也可以extends class
trait T1 extends C1 {...} // T1扩展了类C1
class C2 extends T1 {...} // C1自动变成C2的父类!!
class C3 extends C0 with T1 {...} // 条件:C1是C0的父类!!

10.13 self type机制

  • 问题:如何从编译机制上保证C0是C1的子类?或者更一般地,如何保证T1只能被某个父类(C1)的子类所扩展?
  • 解决方案:在T1的定义里加入self type(自身类型)指定C1
trait T1 {
    this: C1 =>
    ...
} // 指定了T1只能混入C1的子类
  • 还可以指定T1只能混入【带有特定方法】的类,这叫做structural type(结构类型)
trait T1 {
    this: { def getMsg(): String } =>
    ...
} // 指定了T1只能混入带有getMsg方法的类
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 199,064评论 5 466
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 83,606评论 2 376
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 146,011评论 0 328
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 53,550评论 1 269
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 62,465评论 5 359
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 47,919评论 1 275
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,428评论 3 390
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,075评论 0 254
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,208评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,185评论 2 317
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,191评论 1 328
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,914评论 3 316
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,482评论 3 302
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,585评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,825评论 1 255
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,194评论 2 344
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 41,703评论 2 339

推荐阅读更多精彩内容

  • Scala与Java的关系 Scala与Java的关系是非常紧密的!! 因为Scala是基于Java虚拟机,也就是...
    灯火gg阅读 3,404评论 1 24
  • 教材:快学Scalamarkdown阅读:https://www.zybuluo.com/mdeditor cha...
    hakase_nano阅读 1,026评论 0 1
  • 本章要点 类可以实现任意数量的特质 特质可以要求实现它们的类具备特定的字段、方法或超类 和Java接口不同,Sca...
    胡杨1015阅读 763评论 0 0
  • Scala学习笔记: 1.1 scala的基础语法 声明与定义(赋值):声明变量时可以指定类型,不指定也可以自动识...
    哎哟喂喽阅读 554评论 0 2
  • 我们无端的注视星空幻想有一个梦, 在离落的秋风中我们闭着眼睛 我们想春天的蒲公英、 我们想仲夏的萤火虫、 我们想...
    刘凯锋阅读 223评论 0 2