族多态和self类型(Family polymorphism and self types.)Scala的抽象类型概念非常适合于描述相互之间协变的一族(families)类型,这种概念称作族多态。例如:考虑发布/订阅模式,它有两个主要类型:subjects和observers。Subjects定义了subscribe方法,用于给observers进行注册,同时还有一个publish方法,用于通知所有的注册者;通知是通过调用所有注册者的notify方法实现的。一般来说,当subject的状态发生改变时,会调用publish方法。一个subject可以有多个observers,一个observer也可以观察多个subject。Subscribe方法一般用observer的标识为参数,而notify方法则以发出通知的subject对象为参数。因此,这两个类型在方法签名中都引用到了对方。
这个模式的所有要素都在如下系统中:
abstract class SubjectObserver {
type S <: Subject
type O <: Observer
abstract class Subject requires S {
private var observers: List[O] = List()
def subscribe(obs: O) =
observers = obs :: observers
def publish =
for (val obs <- observers) obs.notify(this)
}
trait Observer {
def notify(sub: S): unit
}
}
顶层的SubjectObserver类包含两个类成员:一个用于subject,一个用于observer。Subject类定义了subscribe方法和publish方法,并且维护一个所有注册的observer的列表。Observer这个trait只定义了一个抽象方法notify。
需要注意的是,Subject和Observer并没有直接引用对方,因为这种“硬”引用将会影响客户代码对这些类进行协变的扩展。相反,SubjectOberver定义了两个抽象类型S和O,分别以Subject和Observer作为上界。Subject和observer的类型分别通过这两个抽象类型引用对方。
另外还要注意,Subject类使用了一个特殊的标注requires:
abstract class Subject requires S { ...
这个标注表示Subject类只能作为S的某个子类被实例化,这里S被称作Subject的self-type。在定义一个类的时候,如果指定了self-type,则这个类定义中出现的所有this都被认为属于这个self-type类型,否则被认为是这个类本身。在Subject类中,必须将self-type指定为S,才能保证obs.notify(this)调用类型正确。
Self-type可以是任意类型,并不一定与当前正在定义的类型相关。依靠如下两个约束,类型正确性仍然可以得到保证:(1)一个类型的self-type必须是其所有父类型的子类,(2)当使用new 对一个类进行实例化时,编译器将检查其self-type必须是这个类的父类。
这个publish/subscribe模式中所定义的机制可以通过继承SubjectObserver,并定义应用相关的Subject和Observer类来使用。例如下面的SensorReader对象,将传感器(sensors)作为subjects,而将显示器(displays)作为observers。
object SensorReader extends SubjectObserver {
type S = Sensor
type O = Display
abstract class Sensor extends Subject {
val label: String
var value: double = 0.0
def changeValue(v: double) = {
value = v
publish
}
}
class Display extends Observer {
def println(s: String) = ...
def notify(sub: Sensor) =
println(sub.label + " has value " + sub.value)
}
}
在这个对象中,S被Sensor限定,而O被Display限定,从而原先的两个抽象类型现在分别通过覆盖而获得定义,这种“系绳节”(“tying the knot”)在创建对象实例的时候是必须的。当然,用户也可以再定义一个抽象的SensorReader类型,未来再通过继承进行实例化。此时,这两个抽象类型也可以通过抽象类型来覆盖,如:
class AbsSensorReader extends SubjectObserver {
type S <: Sensor
type O <: Display
...
}
下面的代码演示了SensorReader如何使用:
object Test {
import SensorReader._
val s1 = new Sensor { val label = "sensor1" }
val s2 = new Sensor { val label = "sensor2" }
def main(args: Array[String]) = {
val d1 = new Display; val d2 = new Display
s1.subscribe(d1); s1.subscribe(d2)
s2.subscribe(d1)
s1.changeValue(2); s2.changeValue(3)
}
}
另外值得注意的是其中的import语句,它使Test可以直接访问SensorReader的成员,而无需前缀。Scala的Import比Java中用法更广泛,可以在任何地方使用,可以从任何对象中导入成员,而不仅仅从一个package中。
分享到:
相关推荐
maven-scala-plugin-2.3.jar
Scala 概述(瑞士洛桑联邦理工) Scala 概述(瑞士洛桑联邦理工)
Algebird —Scala的抽象代数工具
sse-chat 这是一个使用和的简单聊天应用程序。 它使用 Concurrent.Broadcast 对象作为 Enumerator,过滤 Enumeratee 和 EventSource 作为 。 这些构建块一起促进了应用程序内的聊天消息数据流。...
scala是一个经典的语言,Scala代表了一个新的语言品种,它抹平了这些人为划分的界限。但是现在scala的相关学习资料不多,因此,本人总结了几篇写的较好的scala学习资料,包含<ScalaQuery_Commerzbank_2011><twitter-...
Scala概述.pptx 变量.pptx 运算符.pptx 程序流程控制.pptx 函数式编程基础.pptx 面向对象编程(基础部分).pptx 面向对象编程(中级部分).pptx 面向对象编程(高级特性).pptx 隐式转换和隐式参数.pptx 集合(上)-基本使用...
【课程列表】 2.1 Scala语言概述 2.2 Scala基础 2.3 面向对象编程基础 2.4 函数式编程基础
scala编程 33章 中文pdf Scala编程实战 目录 第1章字符串. 11 第2章数值39 第3章控制结构.60 第4章类和属性.103 第5章方法147 第6章对象170 第7章包和导入.190 第8章特质200 第9章函数式编程214 第10 章集合242 第...
Programming.in.Scala.pdf
scala-2.12.3 scala-2.12.3 scala-2.12.3 scala-2.12.3
喷雾模板项目 该项目为您自己的喷雾路由工作提供了一个起点... 喷雾罐,Scala 2.11 + Akka 2.3 +喷雾1.3( on_spray-can_1.3_scala-2.11分支) Jetty ,Scala 2.9 + Akka 2.0 + spray 1.0( on_jetty_1.0分支) Jett
scala 编译工具 sbt 安装包。 Little or no configuration required for simple projects Scala-based build definition that can use the full flexibility of Scala code Accurate incremental recompilation ...
Scala 专题教程 - 抽象成员-内含源码以及设计说明书(可以自己运行复现).zip
此文档是讲解实战Scala,希望对喜欢大数据的同学有所帮助!!! 学习Scala语言,不仅仅意味着熟悉新的API,更重要的是一种思维方式的转变。从原有的面向对象编程(OO)到函数式编程(FP)的思想。本书面向实际的使用场景...
2.3 Range 31 2.4 偏函数 32 2.5 方法声明 33 2.5.1 方法默认值和命名参数列表 33 2.5.2 方法具有多个参数列表 34 2.5.3 Future简介 35 2.5.4 嵌套方法的定义与递归 38 2.6 推断类型信息 40 ...
scala2.12.1Windows镜像包
很大篇幅都放在,使用scala实现scala默认库文件的API中,通过对简单的函数式编程逻辑的介绍和实践,主要是实践,建立起来一个比较明晰的scala思维模式,或者叫函数式编程的思维模式。 2 无副作用的函数式编程,同时...
最新制作 scala 2.13.3 API 文档 Html离线版 Scala 是一门多范式(multi-paradigm)的编程语言,设计初衷是要集成面向对象编程和函数式编程的各种特性。 Scala 运行在 Java 虚拟机上,并兼容现有的 Java 程序。
scala3 scala3 scala3 scala3 scala3