您的位置:首页 > 其它

Scala的类型系统支持鸭子类型

2011-11-23 23:59 337 查看
什么是鸭子类型(Duck Typing)?鸭子类型可
解释为,如果一只动物,走起来像鸭子或者叫起来像鸭子,就可以把它当作鸭子。也就是说,如果它含有我想要的功能,那么我可以把它当作真的来对待。举例来说,我需要一个可关闭的类型。那么就需要有一个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;
}

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  鸭子类型 Scala