《Programming In Scala》第18章 Stateful Objects 例子分析。
源程序:
/**
* 《Programming In Scala》第18章 Stateful Objects 例子
*/
package org.stairwaybook.simulation
//模拟器基类
abstract class Simulation {
//模拟动作,为函数
type Action = () => Unit
//工作项目,time为动作启动时间,action为动作
case class WorkItem(time: Int, action: Action)
//当前时间
private var curtime = 0
//取得当前时间
def currentTime: Int = curtime
//工作日程表,例表内项目应按照启动时间的升序排列
private var agenda: List[WorkItem] = List()
//向日程表中加入工作项目,ag为目标日程表,item为被插入项目
private def insert(ag: List[WorkItem], item: WorkItem): List[WorkItem] = {
//按升序插入
if (ag.isEmpty || item.time < ag.head.time) item :: ag
//分割列表,递归调用找到第一个比被插入项目晚的项目
else ag.head :: insert(ag.tail, item)
}
//向内部日程表中插入指定延时后的工作,delay为延时时间,block为工作函数(by name)
def afterDelay(delay: Int)(block: => Unit) {
val item = WorkItem(currentTime + delay, () => block)
agenda = insert(agenda, item)
}
//取得日程表中最前面的工作,并将其从日程表中删除,然后执行该工作
private def next() {
(agenda: @unchecked) match {
case item :: rest =>
agenda = rest
curtime = item.time
item.action()
}
}
//执行模拟
def run() {
//打印开始时间
afterDelay(0) {
println("*** simulation started, time = " + currentTime + " ***")
}
//执行日程表中所有工作
while (!agenda.isEmpty) next()
}
}
//电路模拟基类
abstract class BasicCircuitSimulation extends Simulation {
//反转器延时
def InverterDelay: Int
//结合器延时
def AndGateDelay: Int
//分离器延时
def OrGateDelay: Int
//线路类
class Wire {
//线路值(状态)
private var sigVal = false
//执行动作
private var actions: List[Action] = List()
//取得线路值
def getSignal = sigVal
//设置线路值,当值有变化就执行所有动作
def setSignal(s: Boolean) =
if (s != sigVal) {
sigVal = s
actions foreach (_ ())
}
//加入动作,并且执行一次该动作
def addAction(a: Action) = {
actions = a :: actions
a()
}
}
//加入反转工作
def inverter(input: Wire, output: Wire) = {
def invertAction() {
val inputSig = input.getSignal
afterDelay(InverterDelay) {
output setSignal !inputSig
}
}
//invertAction加入后马上被执行,并且在input的每次状态改变后都会被执行
input addAction invertAction
}
//加入结合工作
def andGate(a1: Wire, a2: Wire, output: Wire) = {
def andAction() = {
val a1Sig = a1.getSignal
val a2Sig = a2.getSignal
afterDelay(AndGateDelay) {
output setSignal (a1Sig & a2Sig)
}
}
//addAction加入后马上被执行,并且在a1或a2中的任意一个状态改变后就会被执行
a1 addAction andAction
a2 addAction andAction
}
//加入分离工作
def orGate(o1: Wire, o2: Wire, output: Wire) {
def orAction() {
val o1Sig = o1.getSignal
val o2Sig = o2.getSignal
afterDelay(OrGateDelay) {
output setSignal (o1Sig | o2Sig)
}
}
//orAction加入后马上被执行,并且在o1或o2中的任意一个状态改变后就会被执行
o1 addAction orAction
o2 addAction orAction
}
//线路监测工作
def probe(name: String, wire: Wire) {
def probeAction() {
println(name +" "+ currentTime + " newvalue = " + wire.getSignal)
}
//加入后马上被执行,并且在wire的每次状态改变后都会被执行
wire addAction probeAction
}
}
//扩展电路模拟类
abstract class CircuitSimulation
extends BasicCircuitSimulation {
//加入半加工作
def halfAdder(a: Wire, b: Wire, s: Wire, c: Wire) {
val d, e = new Wire
orGate(a, b, d)
andGate(a, b, c)
inverter(c, e)
andGate(d, e, s)
}
//加入全加工作
def fullAdder(a: Wire, b: Wire, cin: Wire, sum: Wire, cout: Wire) {
val s, c1, c2 = new Wire
halfAdder(a, cin, s, c1)
halfAdder(b, s, sum, c2)
orGate(c1, c2, cout)
}
}
//文件主单例对象,作为本文件的主执行程序
object App extends Application {
//模拟对象实例
object MySimulation extends CircuitSimulation {
def InverterDelay = 1
def AndGateDelay = 3
def OrGateDelay = 5
}
//引入模拟对象实例中的所有元素
import MySimulation._
//定义线路
val input1, input2, sum, carry = new Wire
//加入监测点
probe("sum", sum)
probe("carry", carry)
//加入半加
halfAdder(input1, input2, sum, carry)
//改变input1的状态
input1 setSignal true
//执行模拟
run()
//改变input2的状态
input2 setSignal true
//执行模拟
run()
}
执行结果:
sum 0 newvalue = false
carry 0 newvalue = false
*** simulation started, time = 0 ***
sum 8 newvalue = true
*** simulation started, time = 8 ***
carry 11 newvalue = true
sum 15 newvalue = false