scala学习手记33 - 使用trait进行装饰
在上一节看到了scala的在实例一级的选择性混入就不得不感叹scala在语法上的扩展性。就通过这样一个特性scala简化了很多在java中的编程概念和设计模式。
比如说在java中常用的组合,以及装饰模式。下面看个书中的例子,详细说说如何使用trait进行装饰。
假设我们要对一个人进行检查,包括信用记录、收支记录、犯罪记录和工作记录等。但是我们并不会总是都会用到所有的检查,比如要买房时会检查信用记录和收支记录,申请出境时会检查犯罪记录和工作记录。
想想该怎么做:最简单的思路是为每种检查创建一个方法,然后在需要的时候将这些方法组合起来。更常用的方案是创建一个检查接口,为每种检查创建一个类,并实现检查方法。为基础的检查,比如信用记录、收支记录创建检查等创建一个基础类还是可行的,但是如果要为每一项具体的检查创建一个类就会面临一个问题:类膨胀。scala可以让我们避免这种问题,使用trait混入实例可以实现面对不同的检查提供不同的处理方案这样的灵活性。
首先我们需要定义一个抽象类Checker,实现一些在检查中的通用的行为:
abstract class Check {
def check(): String = "Checked Application Details..."
}
然后为每一类基础性的检查创建一个trait
trait CreditCheck extends Check {
override def check(): String = "Checked Credit..." + super.check()
}
trait BalanceCheck extends Check{
override def check(): String = "Checked Balance..." + super.check()
}
trait EmploymentCheck extends Check {
override def check(): String = "Checked Employment..." + super.check()
}
trait CriminalRecordCheck extends Check {
override def check(): String = "Check Criminal Records..." + super.check()
}
这些trait都继承自Check。因为我们只想把它混入继承自Check的类。这样做有两个好处:这些trait只能混入继承自Check的类;这些trait可以使用Check的方法。
在每个trait里,都重写了check方法,在重写的同时也引用了Check类的方法,这也可以说是对Check类的修饰或增强。
trait里,通过super调用的方法会经历一个延迟绑定的过程。这个调用并不是对基类的调用,而是对其左边混入的trait的调用——如果这个trait已经是混入的最左trait,那么这个调用就会解析成混入这个trait的类的方法。具体如何可以看一下下面的例子是如何实现的。
来看一个买房申请:
val apartmentApplication = new Check with CreditCheck with BalanceCheck println(apartmentApplication check)
在创建Check实例的同时混入了两个trait:CreditCheck和BalanceCheck。同样的也可以这样实现出境申请:
val exitApplication = new Check with CriminalRecordCheck with EmploymentCheck println(exitApplication check)
可以看出,如果想要按照不同的组合进行检查的话,只需要按照希望的组合将trait混入即可。
上面两段代码的执行结果如下:

最右的trait开始调用check()。然后,顺着super.check(),将调用传递到其左边的trait。最左的trait调用的是真正实例的check()。
在Scala里,trait是一个强有力的工具,可以用它混入横切关注点。使用它们可以以较低的成本创建出高度可扩展的代码。无需创建一个拥有大量类和接口的层次结构,就可以快速地把必要的代码投入使用。
###########
scala学习手记33 - 使用trait进行装饰的更多相关文章
- scala学习手记31 - Trait
不知道大家对java的接口是如何理解的.在我刚接触到接口这个概念的时候,我将接口理解为一系列规则的集合,认为接口是对类的行为的规范.现在想来,将接口理解为是对类的规范多少有些偏颇,更恰当些的观点应该是 ...
- Spark基础-scala学习(三、Trait)
面向对象编程之Trait trait基础知识 将trait作为接口使用 在trait中定义具体方法 在trait中定义具体字段 在trait中定义抽象字段 trait高级知识 为实例对象混入trait ...
- scala学习手记34 - trait方法的延迟绑定
trait的方法的延迟绑定就是先混入的trait的方法会后调用.这一点从上一节的实例中也可以看出来. 下面再来看一个类似的例子: abstract class Writer { def write(m ...
- scala学习手记32 - trait选择性混入
继续上一节. 狗当然是人类的好朋友.但是藏獒呢?这玩意儿又蠢又笨又凶狠,肯定不能算很多人的好朋友了.其实,刚才那句话还可以修正一下下:我们接受的狗才是我们的好朋友. 用程序怎么实现呢?在java里面, ...
- scala学习笔记-面向对象编程之Trait
将trait作为接口使用 1 // Scala中的Triat是一种特殊的概念 2 // 首先我们可以将Trait作为接口来使用,此时的Triat就与Java中的接口非常类似 3 // 在triat中可 ...
- scala学习手记40 - 使用case类
前面两节我们已经多次接触过case关键字了.case关键字不仅可以用在match/case中来执行模式匹配,也可以用来修饰类.不过用case修饰的类也主要是用来做模式匹配.在上一节曾经提到过match ...
- scala学习手记38 - 方法命名约定和for表达式
方法命名约定 之前在学习<运算符重载>一节时曾经说过一个方法命名约定:方法的第一个字符决定了方法的优先级.现在再说另一个命名约定:如果方法以冒号(:)结尾,则调用目标是运算符后面的实例. ...
- scala学习手记23 - 函数值
scala的一个最主要的特性就是支持函数编程.函数是函数编程中的一等公民:函数可以作为参数传递给其他函数,可以作为其他函数的返回值,甚至可以在其它函数中嵌套.这些高阶函数称为函数值. 举一个简单的例子 ...
- scala学习手记17 - 容器和类型推断
关于scala的类型推断前面已经提到过多次.再来看一下下面这个例子: import java.util._ var list1: List[Int] = new ArrayList[Int] var ...
随机推荐
- 习惯养成和目标追踪APP推荐
一.习惯和目标的不同 习惯:贵在坚持,每天任务一定,而完成总量不定.坚持时间越久越好. 目标:贵在按时完成,任务总量一定,但是每天完成量不做限制.有一个完成期限,但是越早越好. 上面的差别导致了相关A ...
- Oracle Schema Objects——Tables——TableType
Oracle Schema Objects Object Tables object type An Oracle object type is a user-defined type with a ...
- IO流入门-第一章-FileInputStream
FileInputStreamj基本用法和方法示例 import java.io.*; public class FileInputStreamTest01 { public static void ...
- 好难忘又伤心一个非常好的学习js群解散了
不知道为什么看到web前端之天天向上这个群解散,好难过.应该可以说,这个群是我见过比较靠谱的群,大家都非常热情帮助.那些管理员管理的非常好,突然解散了.觉得好可惜,也不会因为你是菜鸟不让你加,感觉好可 ...
- 转!!SpringMVC与Struts2区别与比较总结
1.Struts2是类级别的拦截, 一个类对应一个request上下文,SpringMVC是方法级别的拦截,一个方法对应一个request上下文,而方法同时又跟一个url对应,所以说从架构本身上Spr ...
- Linux上free命令的输出及其他
一.明确概念 A buffer is something that has yet to be "written" to disk. A cache is something t ...
- android学习四---Activity和Intent
1.android项目资源深入了解 在深入学习android之前,先好好玩玩手机上的应用,大部分程序都有一个图标,点开图标,程序启动,一定时间后,程序会跳转到第一个界面,比如手机QQ,点开图标,会跳出 ...
- golang SQLite3性能测试
SQLite是个小型的数据库,很简洁,即支持文件也支持内存,比较适合小型的独立项目,在没有网络的时候做一些复杂的关系数据存储和运算. 为了考察性能做10M(1000万)条记录的测试,测试机4CPU.8 ...
- beego——XSRF过滤
跨站请求伪造,简称XSRF,是Web应用中常见的一个安全问题. 当前防范 XSRF 的一种通用的方法,是对每一个用户都记录一个无法预知的token数据, 然后要求所有提交的请求(POST/PUT/DE ...
- http的请求流程
# !/usr/bin/env python # coding:utf-8 import socket def handle_request(client): buf = client.recv(10 ...