koe*_*oen 55 oop closures functional-programming
作为OO开发人员,也许我很难看到它的价值.他们给了什么附加价值?它们适合OO世界吗?
jal*_*alf 67
您可以将其视为类的泛化.
你的班级有一些州.它有一些方法可以使用的成员变量.
闭包只是一种让函数访问本地状态的更方便的方法.
您不必创建一个知道您希望函数使用的局部变量的类,而只需在现场定义函数,它就可以隐式访问当前可见的每个变量.
使用传统OOP语言定义成员方法时,其闭包是"此类中可见的所有成员".
具有"正确"闭包支持的语言只是概括了这一点,因此函数的闭包是"这里可见的所有变量".如果" here "是一个类,那么你有一个传统的类方法.
如果" here "在另一个函数中,那么你就有了函数式程序员所认为的闭包.您的函数现在可以访问父函数中可见的任何内容.
所以这只是一个概括,删除了"函数只能在类中定义"的愚蠢限制,但保持"函数可以看到任何变量在它们被声明的位置可见"的想法.
Gre*_*zky 28
闭包不会给你任何额外的力量.
你可以用它们实现的任何东西,没有它们你都可以实现.
但它们非常适用于使代码更清晰,更易读.而且我们都知道干净可读的短代码是一个更容易调试并且包含更少错误的代码.
让我举几个可能用法的简短Java示例:
button.addActionListener(new ActionListener() {
@Override public void actionPerformed(ActionEvent e) {
System.out.println("Pressed");
}
});
Run Code Online (Sandbox Code Playgroud)
将被替换(如果Java有闭包):
button.addActionListener( { System.out.println("Pressed"); } );
Run Code Online (Sandbox Code Playgroud)
JW.*_*JW. 28
对我来说,闭包的最大好处是当你编写启动任务的代码,让任务运行,并指定任务完成时应该发生什么.通常,在任务结束时运行的代码需要访问开头可用的数据,并且闭包使这变得容易.
例如,JavaScript中的常见用法是启动HTTP请求.谁开始它可能想要控制响应到来时发生的事情.所以你会做这样的事情:
function sendRequest() {
var requestID = "123";
Ext.Ajax.request({
url:'/myUrl'
success: function(response) {
alert("Request " + requestID + " returned");
}
});
}
Run Code Online (Sandbox Code Playgroud)
由于JavaScript的闭包,"requestID"变量被捕获在success函数内部.这显示了如何在同一位置编写请求和响应函数,并在它们之间共享变量.如果没有闭包,则需要将requestID作为参数传递,或者创建包含requestID和函数的对象.
恕我直言它归结为能够捕捉到的代码块和他们的背景下,在一些点以后参考,如果按照要求/时/执行.
它们似乎不是什么大不了的事情,并且闭包绝对不是你每天要完成任务所需要的东西 - 但它们可以使代码更简单,更清晰地编写/管理.
[编辑 - 基于上述评论的代码示例]
Java的:
List<Integer> numbers = ...;
List<Integer> positives = new LinkedList<Integer>();
for (Integer number : integers) {
if (number >= 0) {
positives.add(number);
}
}
Run Code Online (Sandbox Code Playgroud)
Scala(跳过一些其他细节,如类型推断和通配符,所以我们只是比较闭包的效果):
val numbers:List[Int] = ...
val positives:List[Int] = numbers.filter(i:Int => i >= 0)
Run Code Online (Sandbox Code Playgroud)
很遗憾,人们不再在edu中学习Smalltalk;在那里,闭包用于控制结构、回调、集合枚举、异常处理等。对于一个很好的小例子,这里是一个工作队列操作处理程序线程(在 Smalltalk 中):
|actionQueue|
actionQueue := SharedQueue new.
[
[
|a|
a := actionQueue next.
a value.
] loop
] fork.
actionQueue add: [ Stdout show: 1000 factorial ].
Run Code Online (Sandbox Code Playgroud)
并且,对于那些看不懂 Smalltalk 的人来说,JavaScript 语法也是一样的:
var actionQueue;
actionQueue = new SharedQueue;
function () {
for (;;) {
var a;
a = actionQueue.next();
a();
};
}.fork();
actionQueue.add( function () { Stdout.show( 1000.factorial()); });
Run Code Online (Sandbox Code Playgroud)
(好吧,如您所见:语法有助于阅读代码)
编辑:注意 actionQueue 是如何从块内部引用的,它甚至适用于分叉的线程块。这就是使闭包如此易于使用的原因。