定义

特质能够要求混入它的类扩展自还有一个类型,可是当使用自身类型(self type)的声明来定义特质时(this: ClassName =>)。这种特质仅仅能被混入给定类型的子类其中。

如果尝试将该特质混入不符合自身类型所要求的类时,就会报错。

从技术角度上看。自身类型是在类中提到this时,对于this的如果性类型。从有用角度上看,自身类型指定了对于特质能够混入的详细类的需求。如果你的特质仅用于混入还有一个或几个特质。那么能够指定那些如果性的特质。

自身类型在依赖注入的应用

在通过组件构建大型系统,而每一个组件都有不同的实现的时候。我们须要将组件的不同选择组装起来。

通常组件之间存在某种依赖关系,比方,数据訪问组件可能会依赖日志功能。

每一个组件都描写叙述了它所依赖的其它组件的接口,而对实际组件实现的引用是在应用程序被组件起来的时候“注入”的。

对于Scala来说,能够通过特质和自身类型达到简单的依赖注入的效果。

自身类型实现依赖注入

对于日志功能trait Logger {def log(msg: String)},它有两个实现:ConsoleLoggerFileLogger

用户认证特质有对日志功能的依赖,用于记录认证失败:

trait Auth {
this: Logger =>
def login(id: String, password: String): Boolean
}

应用逻辑依赖于上述两个特质,如此定义:

trait App {
this: Logger with Auth =>
...
}

然后我们能够组装应用。object MyApp extends App with FileLogger("test.log") with MockAuth("users.txt")。这里将组件黏合成了一个大类型。

蛋糕模式实现组件配置设计

蛋糕模式能够给出更好的设计。对每一个服务都提供一个组件特质。

组件特质包括:

  • 不论什么所依赖的组件,以自身类型表述
  • 描写叙述服务接口的特质
  • 抽象的val。该val将被初始化成服务的一个实例
  • 能够有选择地包括服务接口的实现
trait LoggerComponent {
trait Logger {...}
val logger: Logger
class FileLogger(file: String) extends Logger {...}
...
} trait AuthComponent {
this: LoggerComponent => //自身类型使得能够訪问日志器 trait Auth {...}
val auth: Auth
class MockAuth(file: String) extends Auth {...}
...
}

这段代码中,我们使用自身类型表示认证组件对日志器组件的依赖。

通过在程序中进行组件配置能够让编译器帮助我们校验模块间的依赖关系:

object AppComponents extends LoggerComponent with AuthComponent {
val logger = new FileLogger("test.log")
val auth = new MockAuth("user.txt")
}

转载请注明作者Jason Ding及其出处

jasonding.top

Github博客主页(http://blog.jasonding.top/)

CSDN博客(http://blog.csdn.net/jasonding1354)

简书主页(http://www.jianshu.com/users/2bd9b48f6ea8/latest_articles)

Google搜索jasonding1354进入我的博客主页

【Scala类型系统】自身类型(self type)引用的更多相关文章

  1. scala类型系统 type关键字

    和c里的type有点像. scala里的类型,除了在定义class,trait,object时会产生类型,还可以通过type关键字来声明类型. type相当于声明一个类型别名: scala> t ...

  2. Scala类型系统——高级类类型(higher-kinded types)

    高级类类型就是使用其他类型构造成为一个新的类型,因此也称为 类型构造器(type constructors).它的语法和高阶函数(higher-order functions)相似,高阶函数就是将其它 ...

  3. scala类型系统:24) 理解 higher-kinded-type

    首先我们从最基本的泛型来看: 现在我们对上面泛型中的类型参数再进一步,也是个泛型会如何呢? 可以看到,java中不支持类型参数也是泛型类型的情况,而scala支持.这是一个很重要的区别,scala在类 ...

  4. 第54讲:Scala中复合类型实战详解

    今天学习了scala的复合类型的内容,让我们通过实战来看看代码: trait Compound_Type1trait Compound_Type2class Compound_Type extends ...

  5. 第53讲:Scala中结构类型实战详解

    今天学习了scala的结构类型,让我们看看代码 class Structural {def open() = print("A class interface opened") } ...

  6. Scala 深入浅出实战经典 第54讲:Scala中复合类型实战详解

    王家林亲授<DT大数据梦工厂>大数据实战视频 Scala 深入浅出实战经典(1-64讲)完整视频.PPT.代码下载:百度云盘:http://pan.baidu.com/s/1c0noOt6 ...

  7. Scala 深入浅出实战经典 第53讲:Scala中结构类型实战详解

    王家林亲授<DT大数据梦工厂>大数据实战视频 Scala 深入浅出实战经典(1-64讲)完整视频.PPT.代码下载:百度云盘:http://pan.baidu.com/s/1c0noOt6 ...

  8. Scala的Option类型

    Scala的Option类型 为了让所有东西都是对象的目标更加一致,也为了遵循函数式编程的习惯,Scala鼓励你在变量和函数返回值可能不会引用任何值的时候使用Option类型.在没有值的时候,使用No ...

  9. 反射,得到Type引用的三种方式

    1.使用System.Object.GetType()得到Type引用 使用一个SportsCar实例得到类型信息 SportsCar sc=new  SportsCar(); Type t=sc.G ...

随机推荐

  1. PHP下mysql驱动概述

    Overview of the MySQL PHP drivers 什么是API? 一 个应用程序接口(Application Programming Interface的缩写),定义了类,方法,函数 ...

  2. Welcome-to-Swift-12附属脚本(Subscripts)

    附属脚本 可以定义在类(Class).结构体(structure)和枚举(enumeration)这些目标中,可以认为是访问对象.集合或序列的快捷方式,不需要再调用实例的特定的赋值和访问方法.举例来说 ...

  3. 【Luogu】P3768简单的数学题(杜教筛)

    题目链接 emm标题全称应该叫“莫比乌斯反演求出可狄利克雷卷积的公式然后卷积之后搞杜教筛” 然后成功地困扰了我两天qwq 我们从最基本的题意开始,一步步往下推 首先题面给出的公式是$\sum\limi ...

  4. vue-cli3 vue.config.js配置

    module.exports = { // 基本路径 baseUrl: '', // 输出文件目录 outputDir: 'dist', // eslint-loader 是否在保存的时候检查 lin ...

  5. Java 学习(2):java 基础概念

    Java作为一种面向对象语言.支持以下基本概念: 多态 继承 封装 抽象 类 对象 实例 方法 重载 基础语法: 一个Java程序可以认为是一系列对象的集合,而这些对象通过调用彼此的方法来协同工作.以 ...

  6. POJ 3037 Skiing

    Skiing Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 4810   Accepted: 1287   Special ...

  7. CSS实现Footer固定底部,超过一屏自动撑开

    方法一:给html.body都设置100%的高度,确定body下内容设置min-height有效,然后设置主体部分min-height为100%,此时若没有header.footer则刚好完美占满全屏 ...

  8. vuejs入门备忘&&用vuecli构建应用

    vuejs框架入门 mvvm图例 这张图足以说明MVVM的核心功能,在这三者里面,ViewModel无疑起着重要的桥梁作用. 一方面,通过ViewModel将Model的数据绑定到View的Dom元素 ...

  9. 转 Vim操作

    传送门 vim全局替换命令   语法为 :[addr]s/源字符串/目的字符串/[option]全局替换命令为::%s/源字符串/目的字符串/g [addr] 表示检索范围,省略时表示当前行.如:“1 ...

  10. Linux--内核Uevent事件机制 与 Input子系统【转】

    转自:http://blog.csdn.net/lxl584685501/article/details/46379453 [-] 一Uevent机制 Uevent在kernel中的位置 Uevent ...