scala学习笔记(5) -- implicit type
关键字: scala functional javascala的implicit def是一个非常重要而且容易被人忽视的特性,通过它能够模拟很多haskell/sml类型系统特有的能力。
考虑如下的接口
- trait Filter[a] {
- def filter(input:a)(f: a=>Boolean):Option[a]
- }
注意由于haskell是纯函数式语言,没有副作用,所以所有的类型都是covariant的。而scala做不到这一点,covarint、contravariant和invariant都会存在,所以这里的泛型参数没有协变。
我们想写一段“万能”的代码处理所有类型的filter操作,于是
- object Filtering{
- def filter[a](input: a)(f: a=> Boolean)(filter: Filter[a]): Option[a] =
- return filter.filter(input)(a)
- }
现在问题来了,不是所有的对象都从Filter接口派生,我们有一个已存在的类,又不想改动既有的代码,怎么办呢?
答案就是implicit type。首先重写Filtering的实现,注意currying的第二个参数定义前加上了implicit
- object Filtering{
- def filter[a](input: a)(f: a=> Boolean)(implicit filter: Filter[a]): Option[a] =
- return filter.filter(input)(f)
- }
对于已存在的类 ExistsClass,我们创建一个新的定义,返回从Filter接口派生的基于ExistsClass的实现
- implicit def implicitExists = new Filter[ExistsClass] {
- def filter(input:ExistsClass)(f: ExistsClass=>Boolean):Option[ExistsClass] =
- if (f(input)) Some(input) else None
- }
这样问题就很简单了,由于implicit参数可以省略,编译器会自动地在编译的时候匹配,所以可以直接调用下面的代码。这样对于写好的抽象代码只需要增加implicit type,就可以无限地扩展到任何已存在的代码中,是不是很cool的性能?现在终于可以肆意地扩展已有的java library了
- scala> Filtering.filter(new ExistsClass)(a => true)
- unnamed20: Option[ExistsClass] = Some(ExistsClass@1dae827)
- scala> Filtering.filter(new ExistsClass)(a => false)
- unnamed21: Option[ExistsClass] = None
最后再介绍一下implicit的另一个重要应用:type view。熟悉design pattern的人都知道wrapper pattern,当需要使用第三方的库又无法直接继承的时候,通常需要手工写一些wrapper method,如果恰巧要扩展的库有很多方法,无疑是一个非常枯燥的工作。通过scala的implicit type,我们可以定义一个类型的某种特殊的view,当compiler遇到一个对类型的未定义操作的时候,会在当前的compiler scope中自动寻找匹配的implicit def,这样对第三方的库进行扩展变成很简单的操作,implicit def一个view函数就好了。这一切都是编译期决定的,不会对性能有太大的损失,而且也保证了类型的安全性。
下面的例子,immuteClass只有simple方法,通过定义wrapperClass和implicit转换函数implicitWrapper,我们为immuteClass增加了一个wrapperClass的view,这样new出来的immuteClass对象(注意是immuteClass对象!)就可以调用wrapperClass的方法了!
- final class immuteClass {
- def simple = println("simple function")
- }
- class wrapperClass(imclass: immuteClass) {
- def advance = println("advance function")
- }
- object MainClass{
- implicit def implicitWrapper(im: immuteClass) = new wrapperClass(im)
- def main(args:Array[String]) {
- val im = new immuteClass
- // call simple method in immuteClass
- im.simple
- // immuteClass doesn't have advance method, so implicitWrapper automaticlly invoked
- // 等价于 implicitWrapper(im).advance
- im.advance
- }
- }
通过上面两个例子我们看到implicit type巨大的潜力,scala的类型系统被称为"Poor Man's Type System",存在于已有的巨大的java资源上面,提供了高效、易于扩展和理解的功能。对scala的抽象类型、泛型的更多心得以后再记录。
- 浏览: 10112 次
- 性别:

- 来自: 北京

- 详细资料
搜索本博客
最近加入圈子
最新评论
-
在scala里调用Hibernate ...
是在JVM上的一种函数式语言,和java可以互相调用,http://www.sc ...
-- by fakechris -
scala学习笔记(1)
用了 Java 的实现描述语法我知道;不过利用了虚类,确实有点新意啊。
-- by Lich_Ray -
scala学习笔记(1)
实际上String=>Unit 是一个scala的trait,相当于java的接 ...
-- by fakechris -
scala学习笔记(1)
var fn = new ( String=>Unit ) { def ap ...
-- by Lich_Ray -
python的小工具,把hibern ...
嗯,输入太工整了正则表达式也就能处理这么工整的代码了,格式比较乱的还是要上ast ...
-- by fakechris






评论排行榜