`
zhouchaofei2010
  • 浏览: 1085904 次
  • 性别: Icon_minigender_1
  • 来自: 上海
社区版块
存档分类
最新评论

scala特质与特质的线性化(转)

 
阅读更多

 

个人感觉最重要几点是,

1、构造器的顺序是类的线性化的反向。线性化是描述某个类型的所有超类型的一种技术规格。  所以当分析线性化的时候可以通过构造器的顺序来分析

 

2、特质的线性化在解决需要粉阶段执行的结构时很有用,通过线性化和调用super实现阶段处理

 

 

原文:http://www.mamicode.com/info-detail-864896.html

 

特质

Scala里相当于Java接口的是Trait(特征)。实际上它比接口还功能强大。与接口不同的是,它还可以定义属性和方法的实现。Scala中特征被用于服务于单一目的功能模块的模块化中。通过混合这种特征(模块)群来实现各种应用程序的功能要求,Scala也是按照这个构想来设计的。

特质的构造顺序

特质也可以有构造器,由字段的初始化和其他特质体中的语句构成。这些语句在任何混入该特质的对象在构造时都会被执行。 
构造器的执行顺序:

  • 调用超类的构造器;
  • 特质构造器在超类构造器之后、类构造器之前执行;
  • 特质由左到右被构造;
  • 每个特质当中,父特质先被构造;
  • 如果多个特质共有一个父特质,父特质不会被重复构造
  • 所有特质被构造完毕,子类被构造。

构造器的顺序是类的线性化的反向。线性化是描述某个类型的所有超类型的一种技术规格。

用作可堆叠改变的特质

特质的一个主要用法是把瘦接口(有较少的方法)转变成胖接口(有较多的方法)。 
其第二个主要用法是为类提供可堆叠的改变。

考虑一个整数队列的例子。队列有两种操作:put,把整数放入队列;get,从尾部取出整数。

import scala.collection.mutable.ArrayBufferabstractclassIntQueue{defget():Intdef put(x:Int)}classBasicIntQueueextendsIntQueue{privateval buf =newArrayBuffer[Int]defget()= buf.remove(0)def put(x:Int)={ buf += x }}

假设定义特质执行如下改动:

  • Doubling: 把所有放入队列的数字加倍
  • Incrementing: 把所有放入队列的数字增加
  • Filtering:从队列中过滤掉负整数

这三种特质代表了改动,因为它们改变了原始队列类的行为而并非定义了全新的队列类。这三种特质是可堆叠的,你可以选择它们混入类中,获得所需改动的全新的类。

//在特质中重写抽象方法traitDoublingextendsIntQueue{abstractoverridedef put(x:Int){super.put(2*x)}}traitIncrementingextendsIntQueue{abstractoverridedef put(x:Int){super.put(x+1)}}traitFilteringextendsIntQueue{abstractoverridedef put(x:Int){if(x >=0)super.put(x)}}

解释:上面的代码定义了超类IntQueue,这个定义意味着该特质只能混入扩展IntQueue的类中 
在特质中声明抽象方法中有super调用,在特质里super调用时动态绑定的;而在类中,由于继承的抽象类,super调用时非法的。这里必须使用abstract override标识符,它意味着特质必须被混入某个具有期待方法的具体定义的类中,这种定义仅在特质定义中使用。

演示:

scala>val queue =newBasicIntQueuewithDoubling
queue:BasicIntQueuewithDoubling= $anon$1@1d3eff4

scala> queue.put(10)

scala> queue.get()
res10:Int=20val queue =newBasicIntQueuewithDoublingwithIncrementing
queue:BasicIntQueuewithDoublingwithIncrementing= $anon$1@19de304

scala> queue.put(-1)

scala> queue.put(2)

scala> queue.put(3)

scala> queue.get
res3:Int=0

scala> queue.get
res4:Int=6

scala> queue.get
res5:Int=8

混入的顺序很重要,越靠近右侧的特质越先起作用。当你调用带混入的类的方法时,最右侧特质的方法首先被调用。如果那个方法调用了super,它调用其左侧特质的方法,以此类推。上面的例子里,Incrementing的put首先被调用,然后Doubing的put第二个被调用。

特质的线性化与多重集成

特质是一种继承多个类似于类的结构的方式,但是它与多重继承有很重要的区别。其中一个尤为重要:super的解释。 
对于多重继承来说,super调用导致的方法调用可以在调用发生的地方明确决定;对于特质来说,方法调用是由类和混入到类的特质的线性化(linearization)所决定的。这种差别使得上面的特质的堆叠成为可能。

在多重继承的语言中,调用相同的方法,编译规则会决定哪个超类最终胜出,而调用该超类的指定方法。 
而在Scala中,当你使用new实例化一个类的时候,Scala把这个类和所有它继承的类还有他的特质以线性的次序放在一起。然后,当你在其中的一个类中调用super,被调用的方法就是方法链的下一节。除了最后一个调用super之外的方法,其净结果就是可堆叠的行为。

线性化细节

Scala 的线性化的主要属性可以用下面的例子演示:假设你有一个类 Cat,继承自超类 Animal 以及两个特质 Furry 和 FourLegged。 FourLegged 又扩展了另一个特质 HasLegs:

classAnimaltraitFurryextendsAnimaltraitHasLegsextendsAnimaltraitFourLeggedextendsHasLegsclassCatextendsAnimalwithFurrywithFourLegged

类 Cat 的继承层级和线性化次序展示在下图。继承次序使用传统的 UML 标注指明:白色箭头表明继承,箭头指向超类型。黑色箭头说明线性化次序,箭头指向 super 调用解决的方向。 
技术分享

当这些类和特质中的任何一个通过super调用了方法,那么被调用的实现将是它线性化的右侧的第一个实现。 
技术分享

参考资料

Scala学习——特质

转载请注明作者Jason Ding及其出处 
GitCafe博客主页(http://jasonding1354.gitcafe.io/) 
Github博客主页(http://jasonding1354.github.io/) 
CSDN博客(http://blog.csdn.net/jasonding1354) 
简书主页(http://www.jianshu.com/users/2bd9b48f6ea8/latest_articles) 
Google搜索jasonding1354进入我的博客主页

分享到:
评论

相关推荐

    Scala Trait(特质).html

    Scala Trait(特征) 1.Scala中没有接口(interface)的概念 2.特质用于在类之间共享程序...5.特质不能被实例化,因此没有构造参数,类似Java接口 6.特质使用“trait”关键字定义 7.实现特质中的方法使用“override”

    Scala考试题1

    1.var,val和def三个关键字之间的区别 2.trait(特质)和abstract class(抽象类)的区别 3.object和class的区别 4.c

    Scala继承和特质.md

    Scala继承和特质.md

    Scala—— 10.trait特质(接口)(未完待续)

    Scala语言中,采用特质trait(特征)来代替接口的概念,也就是说,多个类具有相同的特质(特征)时,就可以将这个特质(特征)独立出来,采用关键字trait声明。理解trait等价于(interface+abstract class)。 1.trait的声明...

    机器学习,scala,线性代数

    内容包括了, scala, 机器学习,线性代数 相关PDF文件

    scala编程中文pdf

    scala编程 33章 中文pdf Scala编程实战 目录 第1章字符串. 11 第2章数值39 第3章控制结构.60 第4章类和属性.103 第5章方法147 第6章对象170 第7章包和导入.190 第8章特质200 第9章函数式编程214 第10 章集合242 第...

    sjson, 具有 Scala 对象序列化功能的Scala Json.zip

    sjson, 具有 Scala 对象序列化功能的Scala Json sjson: Scala 中的透明JSON序列化sjson为 Scala 对象提供非侵入性序列化。 可以使用sjson来序列化内置类型。基本通用数据类型和你设计的任何自定义数据类型。 现在...

    scala与spark文档合集

    scala与spark文档合集,有好多本,包括快学Scala,scala与spark文档合集

    scala编写的dubbo自动化部署工具

    自动用scala写的dubbo服务自动化部署工具,工程是eclipse编写的

    scala sdk 与spark版本冲突

    scala sdk-2.12 与spark版本冲突,spark-1.6最高支持scala sdk-2.10.x版本

    scala与spark基础

    本资源收集了scala与大数据spark的基础的学习笔记,有兴趣的同学可以下载学习

    scala sdk scala-2.12.3

    scala-2.12.3 scala-2.12.3 scala-2.12.3 scala-2.12.3

    scala java 简体、繁体互转换,判断是否为简体、繁体

    可以用scala ,也可以用java,我主要的目的是用来判断汉字是否为繁体,

    Scala编程实战.zip

    此文档是讲解实战Scala,希望对喜欢大数据的同学有所帮助!!! 学习Scala语言,不仅仅意味着熟悉新的API,更重要的是一种思维方式的转变。从原有的面向对象编程(OO)到函数式编程(FP)的思想。本书面向实际的使用场景...

    Scala基础与实践

    Scala是一门多范式的编程语言,一种类似java的编程语言 ,设计初衷是实现可伸缩的语言、并集成面向对象编程和函数式编程的各种特性。

    scala-sbt-scala编译工具

    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 ...

    idea的scala的插件

    idea的scala的插件 idea的scala的插件 idea的scala的插件

    Scala程序设计(第2版)

    第18章 Scala与大数据 386 18.1 大数据简史 386 18.2 用Scala改善MapReduce 387 18.3 超越MapReduce 392 18.4 数学范畴 393 18.5 Scala数据工具列表 394 18.6 本章回顾与下一章提要 394 第19章...

    scala2.12.1Windows镜像包

    scala2.12.1Windows镜像包

Global site tag (gtag.js) - Google Analytics