6. 合成(composition)
解释了Scala的类型抽象体系之后,本节主要描述类的合成方式(译注:class composition似乎也没有固定的译法,此处翻译成“合成”)。Scala的基于混入的类合成(mixin class composition)体系是Brach[6]中的面向对象的线性混入合成(linear mixin compostion)和[14、25]中提出的更加对称的混入模块(mixin modules),以及traits[42]这三者的融合。(注:mixin有些人翻译成混合,有些人翻译成混入)我们先看一个例子,如下这个迭代器的抽象描述:
trait AbsIterator[T] {
def hasNext: boolean
def next: T
}
注意上面出现的关键字trait。Trait是一种特殊的抽象类,他的构造子没有任何值参数。Traits可以出现任何抽象类可以出现的地方,但反之不然,只有traits可以用于混入。
下面,我们用一个trait继承自AbsIterator,并增加一个方法foreach,用于将一个函数作用于该迭代子返回的每一个元素上。
trait RichIterator[T] extends AbsIterator[T] {
def foreach(f: T => unit): unit =
while (hasNext) f(next)
}
下面是一个具体的迭代子类定义,用于连续返回一个字符串的每一个字符:
class StringIterator(s: String) extends AbsIterator[char] {
private var i = 0
def hasNext = i < s.length
def next = { val x = s charAt i; i = i + 1; x }
}
混入式类合成(Mixin-class composition)下面我们将RichIterator和StringIterator的功能合并在一个类中。只有单根继承和接口的情况下这是不可能的,因为这两个类都有具体的实现代码。因此,Scala提供了混入式类合成的机制,使程序设计者可以重用一个类的增量内容,也就是非继承的内容。这种机制使人可以将RichIterator和StringIterator合并,在如下所示的例子将一个字符串的所有字母打成一列。
object Test {
def main(args: Array[String]): unit = {
class Iter extends StringIterator(args(0))
with RichIterator[char]
val iter = new Iter
iter foreach System.out.println
}
}
Iter类通过RichIterator和StringIterator这两个父类型混入合成,第一个父类型仍然称为超类(superclass),第二个父类型则称为混入(mixin)。
类的全序化(Class Linearization)
混入式类合成是多重继承的一种形式,因此也会面临单继承所没有的问题。最典型的就是:如果多个父类型定义了同名的成员,哪一个成员被继承?调用父类方法时那一个成员被引用?如果一个类从多个路径被继承了怎么办?在Scala中,解决这些问题的基础构造就是类的全序化(class linearization)。(注:linearization可以翻成线性化或者全序化,在计算机领域一般取后者。另外,后面大部分情况下用全序来替代,主要是为了读起来不那么别扭)
一个类C所直接继承的类形成的可递闭包当中所有类称为C的基类(base classes)。由于有混入类,一个类与它的基类之间的继承关系,构成一个有向无环图(directed acyclic graph)。C的全序化L(C)是C的所有基类的一个全序(total order),根据如下规则构成:假设C的定义为:
class C extends B0 with . . . with Bn { . . . } .
这个全序以C的基类B0的全序为最后一部分,前面是B1的全序(排除掉已经包含在B0的全序当中的类),再前面是B2,…Bn,同样排除掉前面已经出现过的类。最前面的是类C本身,作为这个全序的头一个类。例如,Iter类的全序化是:
{Iter, RichIterator, StringIterator, AbsIterator, AnyRef, Any }
类的全序对于类的继承关系而言是一种改进:如果一个类C是D的子类,则在任何同时继承C、D的类的全序中,C永远出现在D之前。全序化还满足另一个性质:一个类的全序永远包括其基类的全序作为后缀。例如,StringIterator的全序化:{ StringIterator, AbsIterator, AnyRef, Any }就是其子类Iter的全序的后缀。不过对于混入类,这个性质并不成立,一个混入类的全序当中的类,在其子类的全序当中可能以不同的顺序出现,也就是说,Scala中全序化不是单调(monotonic[1])的。
分享到:
相关推荐
Scala 概述(瑞士洛桑联邦理工) Scala 概述(瑞士洛桑联邦理工)
Scala概述.pptx 变量.pptx 运算符.pptx 程序流程控制.pptx 函数式编程基础.pptx 面向对象编程(基础部分).pptx 面向对象编程(中级部分).pptx 面向对象编程(高级特性).pptx 隐式转换和隐式参数.pptx 集合(上)-基本使用...
scala-2.12.3 scala-2.12.3 scala-2.12.3 scala-2.12.3
mainecoon, 在 Scala 中,变换并合成tagless最终编码代数 Mainecoon是一个小型库,用于转换和编写tagless最终编码代数。安装Mainecoon在 Scala 2.11,2.12和scalajs上可用。 宏注释使用 scalameta插件开发,因此在你...
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,希望对喜欢大数据的同学有所帮助!!! 学习Scala语言,不仅仅意味着熟悉新的API,更重要的是一种思维方式的转变。从原有的面向对象编程(OO)到函数式编程(FP)的思想。本书面向实际的使用场景...
scala2.12.1Windows镜像包
scala3 scala3 scala3 scala3 scala3
scala是一个经典的语言,Scala代表了一个新的语言品种,它抹平了这些人为划分的界限。但是现在scala的相关学习资料不多,因此,本人总结了几篇写的较好的scala学习资料,包含<ScalaQuery_Commerzbank_2011><twitter-...
很大篇幅都放在,使用scala实现scala默认库文件的API中,通过对简单的函数式编程逻辑的介绍和实践,主要是实践,建立起来一个比较明晰的scala思维模式,或者叫函数式编程的思维模式。 2 无副作用的函数式编程,同时...
最好的scala 学习课件,最好的scala 学习课件,学习spark必备
scala编程 33章 中文pdf Scala编程实战 目录 第1章字符串. 11 第2章数值39 第3章控制结构.60 第4章类和属性.103 第5章方法147 第6章对象170 第7章包和导入.190 第8章特质200 第9章函数式编程214 第10 章集合242 第...
scala编程进阶过程中不可或缺的书籍之一,详细介绍了scala语言的各种中高级语法,对于初学和高级开发人员有很大帮助
最新制作 scala 2.13.3 API 文档 Html离线版 Scala 是一门多范式(multi-paradigm)的编程语言,设计初衷是要集成面向对象编程和函数式编程的各种特性。 Scala 运行在 Java 虚拟机上,并兼容现有的 Java 程序。
scala eclipse插件 拷贝到相应的目录即可使用,百度一大堆
快学scala 完整清晰版 大数据spark 主要的编程语言 快学scala 完整清晰版 大数据spark 主要的编程语言
这个打包文件中包含了《SCALA程序设计-JAVA虚拟机多核编程实战》《Scala编程-中文-完整版》《Scala in Action》三本书,足以让你从scala入门到精通,让我们一起愉快的学习吧。spark,scala醉了醉了。哈哈
scala SDK 2.10下载scala SDK 2.10下载scala SDK 2.10下载scala SDK 2.10下载scala SDK 2.10下载scala SDK 2.10下载scala SDK 2.10下载scala SDK 2.10下载scala SDK 2.10下载scala SDK 2.10下载scala SDK 2.10下载...
scala 安装包scala 安装包scala 安装包scala 安装包scala 安装包scala 安装包