Scala的类型系统支持鸭子类型
2011-11-23 23:59
337 查看
什么是鸭子类型(Duck Typing)?鸭子类型可
解释为,如果一只动物,走起来像鸭子或者叫起来像鸭子,就可以把它当作鸭子。也就是说,如果它含有我想要的功能,那么我可以把它当作真的来对待。举例来说,我需要一个可关闭的类型。那么就需要有一个close方法,但我不关心这个close是一个File或Channel或其他任何对象类型,只要它含有这个close方法即可。在Java中通常需要会定义一个叫Closable的接口
然后让相关的类实现这个接口。假如我又需要一个含有process方法的类型,以便能提供给外部系统进行回调,那么又要定义一个包含该方法的接口。
你渐渐发现我们创造了大量的接口和模板类,但糟糕的是,如果在既成事实之后再考虑这个接口是不可能的。如果你先写了这个类,那么这个类就是已经存在的,你就不可以在不破坏源代码的情况下再添加新接口,除非你控制所有客户端。
Scala能解决上述的问题。你只需使用type关键字说明一种类型,比如带有close方法的类型。那么只要哪个对象具有close方法,就能被统一处理,而不需要改动原来的代码。说得有点抽象,来一个实际的例子.
注意观察,Resource1和Resource2是两个独立的类,两者都没有混入什么特质(trait)或继承自某个父类,但由于都具有close方法,在逻辑上具有某种相似性(即都是需要主动关闭的资源),因此通过声明一种类型(Closable)来统一调用close方法。这种语言特性对于设计非入侵性的框架或者改造旧系统(比如为某几类接口声明一个统一接口)十分有用。在Java中如果要实现这种效果,就需要借助一些第三方的工具对类进行增强。
经过上面的解释,你能看懂下面的这段代码么?
解释为,如果一只动物,走起来像鸭子或者叫起来像鸭子,就可以把它当作鸭子。也就是说,如果它含有我想要的功能,那么我可以把它当作真的来对待。举例来说,我需要一个可关闭的类型。那么就需要有一个close方法,但我不关心这个close是一个File或Channel或其他任何对象类型,只要它含有这个close方法即可。在Java中通常需要会定义一个叫Closable的接口
public interface Closable{ public void close(); }
然后让相关的类实现这个接口。假如我又需要一个含有process方法的类型,以便能提供给外部系统进行回调,那么又要定义一个包含该方法的接口。
你渐渐发现我们创造了大量的接口和模板类,但糟糕的是,如果在既成事实之后再考虑这个接口是不可能的。如果你先写了这个类,那么这个类就是已经存在的,你就不可以在不破坏源代码的情况下再添加新接口,除非你控制所有客户端。
Scala能解决上述的问题。你只需使用type关键字说明一种类型,比如带有close方法的类型。那么只要哪个对象具有close方法,就能被统一处理,而不需要改动原来的代码。说得有点抽象,来一个实际的例子.
// 资源管理器 class ResourceManager{ // 定义一个含有close方法的类型 type Closable = { def close(); } //resources 维护着一堆资源引用 private val resources = new scala.collection.mutable.ListBuffer[Closable](); //释放所有托管的资源 def release(){ resources foreach { _.close } } def add(resource: Closable) = resources += resource } // Resource1表示一种资源类型,具有close方法 class Resource1{ def close(){ println("resource1 is closed"); } } // Resource2表示另一种资源类型,也具有close方法 class Resource2{ def close(){ println("resource2 is closed"); } } val manager = new ResourceManager manager.add(new Resource1) manager.add(new Resource2) manager.release()
注意观察,Resource1和Resource2是两个独立的类,两者都没有混入什么特质(trait)或继承自某个父类,但由于都具有close方法,在逻辑上具有某种相似性(即都是需要主动关闭的资源),因此通过声明一种类型(Closable)来统一调用close方法。这种语言特性对于设计非入侵性的框架或者改造旧系统(比如为某几类接口声明一个统一接口)十分有用。在Java中如果要实现这种效果,就需要借助一些第三方的工具对类进行增强。
经过上面的解释,你能看懂下面的这段代码么?
object ResourceManager{ private val pool = new scala.collection.mutable.ListBuffer[{ def close(): Unit }]; def borrowResource(): { def close(): Unit } = { println("borrow a resource from pool"); // 简单起见,这里直接new一个临时对象返回 new { def close()= println(" close resource "); } } def addResource(resource: { def close(): Unit } ) = { println("add a resource to pool"); pool += resource; } }
相关文章推荐
- C语言数据类型是如何被大多数计算机系统所支持?
- Scala 容器与类型系统之编程进阶(3)
- Linux下如何查看当前支持的文件系统及各分区的文件系统类型
- 深入理解Scala中的类型系统
- scala类型系统:1) 类型与类
- Scala模式匹配和类型系统
- scala类型系统:20) 数组类型
- Scala in depth 6 Scala的类型系统 上
- scala类型系统:13) context bounds
- scala类型系统:3) 单例类型与this.type
- Scala 类型系统编程 有点复杂 ,也是重点
- scala类型系统:16) 函数类型
- day4-Scala模式匹配、类型系统
- Revit2014 支持编程创建管道并且立即赋予系统类型名称
- scala类型系统:4) 内部类,路径依赖类型&类型投影
- scala类型系统:19) Manifest与TypeTag
- C语言数据类型是如何被大多数计算机系统所支持?
- scala类型系统:12) view bounds
- Scala类型系统编程
- Scala讲座:类型系统和相关功能