C#和Java的闭包-Jon谈《The Beauty of Closures》
原文:http://csharpindepth.com/Articles/Chapter5/Closures.aspx
第一段略。。。
大多数讲闭包的文章都是说函数式语言,因为它们往往对闭包的支持最完善。当你在使用函数式语言时,很可能已经清楚了解了什么是闭包,所以我想写一篇在经典OO语言出现的闭包有什么用处应该也是很合适的事情。这篇文章我准备讲一下C#(1、2、3)和JAVA(7以前版本)的闭包。
什么是闭包?
简单来讲,闭包允许你将一些行为封装,将它像一个对象一样传来递去,而且它依然能够访问到原来第一次声明时的上下文。这样可以使控制结构、逻辑操作等从调用细节中分离出来。访问原来上下文的能力是闭包区别一般对象的重要特征,尽管在实现上只是多了一些编译器技巧。
利用例子来观察闭包的好处(和实现)会比较容易, 下面大部份内容我会使用一个单一的例子来进行讲解。例子会有JAVA和C#(不同版本)来说明不同的实现。所有的代码可以点这里下载。
需求场景:过滤列表
按一定条件过滤某个列表是很常见的需求。虽然写几行代码遍历一下列表,把满足条件的元素挑出来放到新列表的“内联”方式很容易满足需求,但把判断逻辑提取出来还是比较优雅的做法。唯一的难点就是如何封装“判定一个元素是否符合条件”逻辑,闭包正好可以解决这个问题。
虽然我上面说了“过滤”这个词,但它可能会有两个截然不同的意思“把元素滤出来放到列表里”或者把“把元素滤出来扔掉”。比如说“偶数过滤”是把“偶数”保留下来还是过滤掉?所以我们使用另一个术语“断言”。断言就是简单地指某样东西是不是满足某种条件。在我们的例子中即是生成一个包含了原列表满足断言条件的新列表。
在C#中,比较自然地表现一个断言就是通过delegate,事实上C# 2.0有一个Predicate<T>类型。(顺带一提,因为某些原因,LINQ更偏向于Func<T, bool>;我不知道这是为什么,相关的解释也很少。然而这两个泛型类的作用其实是一样的。)在Java中没有delegate,因此我们会使用只有一个方法的interface。当然C#中我们也可以使用interface,但会使得代码看起来很混乱,而且不能使用匿名函数和拉姆达表达式-C#中符合闭包特征的实现。下面的interface/delegate供大家参考:
// Declaration for System.Predicate<T>
public delegate bool Predicate<T>(T obj)
// Predicate.java
public interface Pred
相关文档:
前言
在Java语言中,equals()和hashCode()两个函数的使用是紧密配合的,你要是自己设计其中一个,就要设计另外一个。在多数情况 下,这两个函数是不用考虑的,直接使用它们的默认设计就可以了。但是在一些情况下,这两个函数最好是自己设计,才能确保整个程序的正常运行。最常见的是当 一个对象被加入集合对象(collectio ......
参考代码:
class SuperClass {
private int n;
SuperClass() {
System.out.println("SuperClass()");
}
SuperClass(int n) {
System.out.println("SuperClass(" + n + ")");
this.n = n;
}
}
class SubClass extends SuperClass {
private int n ......
try {
Runtime.getRuntime().exec("C:\\xxx.exe");
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} ......
注释的原则 1、 注释形式统一 在整个应用程序中,使用具有一致的标点和结构的样式来构造注释。如果在其他项目组发现他们的注释规范与这份文档不同,按照他们的规范写代码,不要试图在既成的规范系统中引入新的规范。 2、 注释的简洁 内容要简单、明了、含义准确,防止注释的多义性,错误的注释不但无益反而有害。 ......