延迟构造

DelayedInit特质是为编译器提供的标记性的特质。整个构造器被包装成一个函数并传递给delayedInit方法。

  1. trait DelayedInit {
  2. def deayedInit(x : Unit) : Unit
  3. }

这个方法接受一个函数对象,函数对象里包含了全部的一般的构造器逻辑

  1. trait App extends DelayedInit{
  2. var x : Option[Function0[Unit]] = None
  3. override def delayedInit(cons : => Unit){
  4. x = Some(() => cons)
  5. }
  6. def main(args : Array[String]) : Unit =
  7. x.foreach(_())
  8. }

如上代码,它定义了一个Option x用来容纳构造器行为。覆盖了delayedInited方法。在X变量里存放构造器逻辑,main方法去执行存放在x变量里的构造器逻辑。

DelayedInit特质可以用于延迟整个对象的构造过程,直到所有属性都被注入完成。

多重继承

为特质的抽象方法提供空实现

首先创建一个SimulationEntity类,只有一个handleMesaage方法,用于接收一个消息对象和一个上下文对象

  1. trait SimulationEntity{
  2. def handleMessage(msg : SimulationMessage,ctx : SimulationContext) : Unit
  3. }

模拟系统设计为让每个节点通过在上下文传递的消息。当一个实体收到消息时,它更新自身当前状态并发送对应于该状态的消息。上下文也可以用来在后面的模拟中(对各实体的行为)进行调度。

下来定义一个简单的NetworkEntity特质和对应的行为(behavior)

  1. trait NetworkEntity{
  2. def getMacAddress(ip : String) : String
  3. def hasIpAddress(addr : String) : Boolean
  4.  
  5. def handleMessage(msg : SimulationMessage,ctx : Simulation) : Unit = msg match{
  6. case PingRequest(ip,sender) if hasIpAddress(ip) =>
  7. ctx respond(sender,PingResponse(getMacAddress(ip)))
  8. case _=>
  9. super.handleMessage(msg)
  10. }
  11. }

尝试空实现的特质

  1. trait MixableParent extends SimulationEntity{
  2. override def handleMessage(msg : SimulationMessage, ctx : SimulationContext) : Unit = {}
  3. }
  4.  
  5. trait NetWorkENntity exntends MixableParent{
  6. def getMacAddress(ip : String) : String
  7. def hasIpAddress(addr : String ) : Boolean
  8.  
  9. override SimulationContext) : Unit = msg match{
  10. case PingRequest(ip , sender) if hasIpAddress(ip) => ctx respond(sender, PingResponse(getMacAddress(ip), this))
  11. case _=>
  12. super.handleMessage(msg,ctx)
  13. }
  14. }
  15.  
  16. class Router extends SimulationEntity{
  17. override def handleMessage(msg : SimulationMessage,
  18. case Test(x) => println("YAY!" + x)
  19. case _=>
  20. }
  21. }

和Simulation类交互

  1. val rtr = new MixableParent with Router with DummyNetworkEntity
  2.  
  3. rtr.handleMessage(Test(5),null)
  4.  
  5. val ctx = new SimulationContext{
  6. override def respond(entity : SimulationEntity,msg : SimulationMessage ) : Unit = {
  7. println("Sending " + msg + " to " + entity)
  8. }
  9. }
  10.  
  11. rtr.handleMessage(PingRequest("HAI",rtr),ctx)

所以在通过特质创建可混入的层级结构时,需要确保有一个特质可以假定为父类的"混入点(you have a "mixin" point that traits can asuume as parent")

组合可以包含继承

由于Java不支持多重继承,因此当子类需要组合两个类的行为时,只能继承其中一个,而不得不重新实现另一个。

那么下述案例 基于继承来组合Logger 和 DataAccess

  1. trait logger{
  2. def log(category : String , msg : String ) : Unit = {
  3. println(msg)
  4. }
  5. }
  6.  
  7. traqit DataAccess{
  8. def query[A](in : String) : A = {
  9. ...
  10. }
  11. }
  12.  
  13. trait LoggedDataAccess extends DataqAccess with Logger{
  14. def query[A](in : String) : A = {
  15. log("QUERRY", in)
  16. super.query(in)
  17. }
  18. }

好不习惯。。。学的太尼玛痛苦了T T

Scala第四章学习笔记(面向对象编程)的更多相关文章

  1. Spring实战第四章学习笔记————面向切面的Spring

    Spring实战第四章学习笔记----面向切面的Spring 什么是面向切面的编程 我们把影响应用多处的功能描述为横切关注点.比如安全就是一个横切关注点,应用中许多方法都会涉及安全规则.而切面可以帮我 ...

  2. 《Linux内核设计与实现》第四章学习笔记

    <Linux内核设计与实现>第四章学习笔记           ——进程调度 姓名:王玮怡  学号:20135116 一.多任务 1.多任务操作系统的含义 多任务操作系统就是能同时并发地交 ...

  3. 《Linux内核设计与实现》第四章学习笔记——进程调度

                                                                        <Linux内核设计与实现>第四章学习笔记——进程调 ...

  4. 《Linux命令行与shell脚本编程大全》 第十四章 学习笔记

    第十四章:呈现数据 理解输入与输出 标准文件描述符 文件描述符 缩写 描述 0 STDIN 标准输入 1 STDOUT 标准输出 2 STDERR 标准错误 1.STDIN 代表标准输入.对于终端界面 ...

  5. Day4 《机器学习》第四章学习笔记

    决策树 前几天学习了<机器学习>的前三章,前三章介绍机器学习的基础知识,接下来,第四章到第十章介绍一些经典而常用的机器学习方法,这部分算是具体的应用篇,第四章介绍了一类机器学习方法——决策 ...

  6. Mudo C++网络库第四章学习笔记

    C++多线程系统编程精要 学习多线程编程面临的最大思维方式的转变有两点: 当前线程可能被切换出去, 或者说被抢占(preempt)了; 多线程程序中事件的发生顺序不再有全局统一的先后关系; 当线程被切 ...

  7. Scala第三章学习笔记

    换行后的左大括号造成的问题: class FooHolder { def foo() { println("foo was called") } } Scala认为def foo( ...

  8. 4类Storage方案(AS开发实战第四章学习笔记)

    4.1 共享参数SharedPreferences SharedPreferences按照key-value对的方式把数据保存在配置文件中,该配置文件符合XML规范,文件路径是/data/data/应 ...

  9. 菜单Menu(AS开发实战第四章学习笔记)

    4.5 菜单Menu Android的菜单主要分两种,一种是选项菜单OptionMenu,通过按菜单键或点击事件触发,另一种是上下文菜单ContextMenu,通过长按事件触发.页面的布局文件放在re ...

随机推荐

  1. tiny4412SD启动盘的制作--1

    一.使用SD-flasher工具烧写superboot到SD卡. 1.SD-Flasher.exe 会对 SD 卡进行分区,第一个分区为 130M 用于存放 Superboot4412, 剩下的空间格 ...

  2. DuiLib——第二篇UIBase

    ---------------------------------------------------------------------------------- 分析约定: private o-- ...

  3. Valgrind简单用法

    Valgrind的主要作者Julian Seward刚获得了今年的Google-O'Reilly开源大奖之一──Best Tool Maker.让我们一起来看一下他的作品.Valgrind是运行在Li ...

  4. MySQL-使用tcpdump排查MySQLl数据库tps飙升的问题

    可以直接输出 tcpdump -i eth1 -s -l - | strings | perl -e ' while(<>) { chomp; next if /^[^ ]+[ ]*$/; ...

  5. 使用seajs来引入js代码

    注意的是:引入jquery的代码最好放在html文件中,本文是为了说明seajs中require如何使用的,才将jquery放入seajs中的. html中对应的代码: <script type ...

  6. window.parent与window.openner

    window.parent与window.openner区别介绍 作者: 字体:[增加 减小] 类型:转载 今天总结一下js中几个对象的区别和用法,对这几个概念混淆的朋友可以看看 今天总结一下js中几 ...

  7. xfs文件系统

    引用http://blog.chinaunix.net/uid-522675-id-4665059.html xfs文件系统使用总结 1.3 xfs相关常用命令xfs_admin: 调整 xfs 文件 ...

  8. openpgp和gnupg

    http://www.openpgp.org/about_openpgp/history.shtml https://www.gnupg.org/ History OpenPGP is a non-p ...

  9. Linux中的free命令

    解释一下Linux上free命令的输出. 下面是free的运行结果,一共有4行.为了方便说明,我加上了列号.这样可以把free的输出看成一个二维数组FO(Free Output).例如: FO[2][ ...

  10. commonJS规范基本机构

    commonJS规范:使用 module.exports 和 require ,基本结构如下: // foo.js 输出模块 module.exports = function(x) { consol ...