scala 学习笔记(06) OOP(下)多重继承 及 AOP
一、多继承
上篇trait中,已经看到了其用法十分灵活,可以借此实现类似"多重继承"的效果,语法格式为:
class/trait A extends B with C with D ...
之所以要给多重继承加一个引号,是因为这有约束条件的,上面的语法中,从左向右看,extends 后的B是A的基本类型,不管后面接多少个trait,如果C或D,本身又继承自其它class(上一篇讲过,trait也可以继承自class),则C或D的基类必须与B的基类保持一致,否则的话,JVM上的OOP世界观将被彻底颠覆,scala编译出来的class,也就没办法与java兼容了,这个原则,我个人叫做『同宗同源』,很容易理解,必须认同共同的祖先!当然,如果C或D,本身只是纯粹的trait,不继承自其它任何类,这就相当于一个A继承自B,同时实现了多个接口,跟java中的理解一致。
package yjmyzz /**
* 动物基类
*/
class Animal {} trait Fly {
println("4 -> Fly") def fly
} trait Swim {
def swim
} class FlyAnimal extends Animal with Fly {
override def fly: Unit = println("I believe I can fly. I believe I can touch the sky")
} trait FlyAndSwim extends Fly with Swim { } /**
* 神基类
*/
class God {
println("1 -> God")
} /* with关键字只能用于trait,而不能是class
class HalfGod extends God with Animal{
//Error:(14, 32) class Animal needs to be a trait to be mixed in
//class HalfGod extends God with Animal{}
}
*/ trait Magic extends Animal {
def showMagic
} /* 无效继承,因为HalfGod的基类为God,而magic的基类为Animal,它俩不是同一祖宗!
class HalfGod extends God with magic {
//Error:(45, 32) illegal inheritance; superclass God
// is not a subclass of the superclass Animal
// of the mixin trait magic override def showMagic: Unit = println("I have some magic!")
}
*/ trait SuperPower {
println("2 -> SuperPower") def superPower;
} /**
* "有超能力的"神
*/
class SuperPowerGod extends God with SuperPower {
println("3 -> SuperPowerGod") override def superPower: Unit = println("I have super power!")
} /**
* "会飞的"神
*/
trait FlyGod extends God with Fly {
println("5 -> FlyGod") override def fly: Unit = println("I can fly!")
} /**
* 多继承示例(SuperPowerGod与FlyGod都是God的子类,因此类型兼容,编译通过)
*/
class MyGod extends SuperPowerGod with FlyGod {
println("6 -> MyGod") } object TestApp { def main(args: Array[String]) {
var obj = new MyGod
/*
1 -> God
2 -> SuperPower
3 -> SuperPowerGod
4 -> Fly
5 -> FlyGod
6 -> MyGod
*/
}
}
代码略长,但是并不难理解。比较有意思的是构造函数的调用顺序,从输出结果看,大致遵循下面的原则:
1、先调用父类的构造器(即:extends B中B的构造器,如果B还有父类,则先向上找,直到找到最高层的父类,然后调用顶级父类的构造器)
2、然后再调用With后的Trait的构造器,
a)如果Trailt本身继承自其它Class,则看下这个Class是不是步骤1中的父类,如果是的,就不重复调用了,最后输出的4 -> Fly 前,并没有重复输出1 -> God 就说明了这一点
b) 调用Trait本身的构造器
3、上述过程反复处理,只到把所有层级的基类处理完
4、最后再调用本身的构造器
二、AOP
谈AOP之前,先来看看Scala的晚绑定:
package yjmyzz
trait IA {
def foo = println("IA.foo()")
}
trait IAA extends IA{
override def foo = println("IAA.foo()")
}
class A extends IA{
override def foo = println("A.foo()")
}
object TestApp {
def main(args: Array[String]) {
val a = new A with IAA
a.foo
a.asInstanceOf[A].foo
a.asInstanceOf[IA].foo
a.asInstanceOf[IAA].foo
}
}
最后的输出是:
IAA.foo()
IAA.foo()
IAA.foo()
IAA.foo()
即:不管实例a转型为什么类型,最终调用foo时,都是最底层的子类IAA里的foo方法,这就是晚绑定的特点。运行时,最底层的子类IAA已经override了父类的foo方法,所以最终不管怎么折腾,都是IAA里的override版本。
借助这个,就可以很方便的实现AOP,假设我们有一个业务处理类,想在业务处理前后,记录日志,这是典型的AOP方法拦截场景,看下面的示例代码:
package yjmyzz /**
* 业务接口
*/
trait Handler {
def handle;
} /**
* 日志AOP
*/
trait LoggerHandler extends Handler {
//注意这里的abstract不可省略,
//因为super.Handle并没有提供具体实现,而是在运行时,交由具体的子类来实现
abstract override def handle = {
println("log before handle...")
super.handle
println("log after handle...")
}
} /**
* 业务处理类
*/
class BizHandler extends Handler {
override def handle: Unit = println("business processing...")
} object AopTest { def main(args: Array[String]) {
var biz = new BizHandler with LoggerHandler;
biz.handle //这里实际上调用的是LoggerHandler.handle //BizHandler为LoggerHandler的父类,所以运行时,
// LoggerHandler.handle中的super.Handle才是真正调用的BizHandler.handle方法
} }
输出结果:
log before handle...
business processing...
log after handle...
没有反射,没有动态代理,没有借助第3方类库,这是我见过的最简洁的AOP实现。
scala 学习笔记(06) OOP(下)多重继承 及 AOP的更多相关文章
- scala 学习笔记(05) OOP(中)灵活的trait
trait -- 不仅仅只是接口! 接上回继续,scala是一个非常有想法的语言,从接口的设计上就可以发现它的与众不同.scala中与java的接口最接近的概念是trait,见下面的代码: packa ...
- scala 学习笔记(04) OOP(上)主从构造器/私有属性/伴生对象(单例静态类)/apply方法/嵌套类
一.主从构造器 java中构造函数没有主.从之分,只有构造器重载,但在scala中,每个类都有一个主构造器,在定义class时,如果啥也没写,默认有一个xxx()的主构造器 class Person ...
- 机器学习实战(Machine Learning in Action)学习笔记————06.k-均值聚类算法(kMeans)学习笔记
机器学习实战(Machine Learning in Action)学习笔记————06.k-均值聚类算法(kMeans)学习笔记 关键字:k-均值.kMeans.聚类.非监督学习作者:米仓山下时间: ...
- 基于.net的分布式系统限流组件 C# DataGridView绑定List对象时,利用BindingList来实现增删查改 .net中ThreadPool与Task的认识总结 C# 排序技术研究与对比 基于.net的通用内存缓存模型组件 Scala学习笔记:重要语法特性
基于.net的分布式系统限流组件 在互联网应用中,流量洪峰是常有的事情.在应对流量洪峰时,通用的处理模式一般有排队.限流,这样可以非常直接有效的保护系统,防止系统被打爆.另外,通过限流技术手段,可 ...
- iOS学习笔记06—Category和Extension
iOS学习笔记06—Category和Extension 一.概述 类别是一种为现有的类添加新方法的方式. 利用Objective-C的动态运行时分配机制,Category提供了一种比继承(inher ...
- 学习笔记(1)centos7 下安装nginx
学习笔记(1)centos7 下安装nginx 这里我是通过来自nginx.org的nginx软件包进行安装的. 1.首先为centos设置添加nginx的yum存储库 1.通过vi命令创建一个rep ...
- Scala学习笔记及与Java不同之处总结-从Java开发者角度
Scala与Java具有很多相似之处,但又有很多不同.这里主要从一个Java开发者的角度,总结在使用Scala的过程中所面临的一些思维转变. 这里仅仅是总结了部分两种语言在开发过程中的不同,以后会陆续 ...
- Web安全学习笔记 SQL注入下
Web安全学习笔记 SQL注入下 繁枝插云欣 --ICML8 SQL注入小技巧 CheatSheet 预编译 参考文章 一点心得 一.SQL注入小技巧 1. 宽字节注入 一般程序员用gbk编码做开发的 ...
- java学习笔记之OOP(二)
java学习笔记二.面向对象[OOP]Object Oriented Programming 一.三大特性: 1.封装:隐藏对象的属性和实现细节,仅对外提供公共访问方式,将变化隔离,便于使用,提高复用 ...
随机推荐
- 关于Linux与windows传递文件乱码问题
linux下一般是采用utf-8的编码,而我们在windows上编辑文件时是gb2312的编码.所以导致中文编码会乱码.要更正这个问题实际上很简单只要把文件转换成utf-8编码格式然后再导入就ok啦. ...
- v0lt CTF安全工具包
0×00 v0lt v0lt是一个我尝试重组每一个我使用过的/现在在使用的/将来要用的用python开发的安全领域CTF工具.实践任务可能会采用bash脚本来解决,但我认为Python更具有灵活性,这 ...
- 7、软件质量工程师要阅读的书籍 - IT软件人员书籍系列文章
软件质量工程师在项目组中的作用不是那么明显,但是它是软件质量的重要度量标准人员.有句话说:软件质量是生产出来的,不是开发出来的.通过软件质量审查,能够对软件项目的代码等质量进行衡量,最起码要能够对代码 ...
- MapReduce实例-倒排索引
环境: Hadoop1.x,CentOS6.5,三台虚拟机搭建的模拟分布式环境 数据:任意数量.格式的文本文件(我用的四个.java代码文件) 方案目标: 根据提供的文本文件,提取出每个单词在哪个文件 ...
- NuGet学习笔记2——使用图形化界面打包自己的类库
NuGet相对于我们最重要的功能是能够搭建自己的NuGet服务器,实现公司内部类库的轻松共享更新.在安装好NuGet扩展后,我们已经能够通过NuGet轻松下载自己需要的类库,下面来说一说如何将自己的项 ...
- 揭开GrowingIO无埋点的神秘面纱
揭开GrowingIO无埋点的神秘面纱 早在研究用户行为分析的时候,就发现国内的GrowingIO在宣传无埋点技术,最近正好抽出时间来研究一下所谓的无埋点到底是什么样的. 我分六部分来分析一下无埋 ...
- SHA-1 加密算法破解现已只需要 10 天
转自:http://www.linuxeden.com/html/news/20151009/163173.html SHA-1是如今很常见的一种加密哈希算法,HTTPS传输和软件签名认证都很喜欢它, ...
- SQL Server调优系列基础篇(并行运算总结)
前言 上三篇文章我们介绍了查看查询计划的方式,以及一些常用的连接运算符.联合运算符的优化技巧. 本篇我们分析SQL Server的并行运算,作为多核计算机盛行的今天,SQL Server也会适时调整自 ...
- 烂泥:SQL Server 2005数据库安装
本文由秀依林枫提供友情赞助,首发于烂泥行天下. 为了能更好的利用服务器,所以打算把该业务进行迁移.因为该业务比较特殊,需要服务器上有相应的硬件支持,所以打算直接升级该服务器目前的操作系统.目前公司服务 ...
- hw 要的是螺丝钉
日前突然接到华为HR的电话,叫我去面试。本来我的工作和工资收入等各方面在本地也还算可以,没有想要跳槽。但是本着去看看有没有更好机会的想法就去了。 9:30到了现场后,在那里等了很久,一个考官上来问了 ...