Java 匿名类与 Objective-C 块相比的局限性
在发现 Objective-C 中的块之后,我才开始了解一阶函数和闭包。 Java 是另一种我听说过闭包(或缺乏闭包)的语言,以及匿名类如何在某种程度上弥补这一点。
我绝对可以看到 Objective-C 中闭包作为块的优点,但是匿名 Java 类的局限性是什么?它们在多大程度上“某种程度上”弥补了真正封闭的不足?
I'm just starting to wrap my head around first order functions and closures after discovering blocks in Objective-C. Java is another language where I've heard about closures (or lack thereof) and how anonymous classes make up for this somewhat.
I can definitely see the advantages of closures as blocks in Objective-C, but what are the limitations of anonymous Java classes? To what extent do they 'somewhat' make up for the lack of true closures?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
Java 匿名类真的非常非常啰嗦。除了定义它们所需的大量样板之外,Java 的一些设计决策意味着许多常见任务比其他语言要冗长得多。例如,在 Java 中将可变的上值导入到闭包中是一件很痛苦的事情。
基本上,Java 不支持 upvalues;相反,它们是通过类的构造函数的不可见参数将它们(按值)传递到类中来模拟的。因为它们是按值传递的,所以在类内部修改它们不会影响构造该类的方法中的副本,因此编译器会让您将它们声明为 Final 以避免混淆。例如:
在您确实需要修改变量的情况下,例如在几乎所有闭包有用的情况下,您必须作弊:
在这里,
i
本身是仍然是不可变的,但因为它指向一个可变对象,所以我可以更改该对象的内容。 (当然,在现实生活中我会使用类而不是数组,因为使用数组真的很难看。这使得它变得更加罗嗦。)我推测下一个 Java 版本将是有语法糖可以让这一切变得更容易,但现在在 Java 中以闭包为中心的编程相当麻烦。我发现更改逻辑而不使用闭包通常更容易,只是为了让我保持使用的代码量足够小以便易于理解。
Java anonymous classes are really, really wordy. Apart from the vast amounts of boilerplate that you need just to define them, some of Java's design decisions mean that a lot of common tasks are much more verbose than in other languages. For example, importing mutable upvalues into the closure is a pain in the arse in Java.
Basically, Java doesn't support upvalues; instead they're simulated by passing them (by value) into the class via invisible parameters to the class's constructor. Because they're passed by value, modifying them inside the class won't affect the copy in the method that constructed the class, so the compiler makes you declare them final to avoid confusing yourself. e.g.:
On occasions where you do need to modify the variable, for example in pretty much every case where closures would be useful, you have to cheat:
Here,
i
itself is still immutable, but because it points at a mutable object, I can change the contents of the object. (Naturally, in real life I'd use a class rather than an array, because using arrays is really ugly. And that makes it even more wordy.)I gather that the next Java release is going to have syntactic sugar to make all this easier, but right now closure-centric programming is pretty cumbersome in Java. I find it's frequently easier to change the logic not to use closures, simply to allow me to keep the amount of code in use small enough to be comprehensible.
我不太了解 Objective-C 版本的闭包,但我从 Smalltalk 和 Lua 中了解它们。
闭包本质上是一个函数,它可以访问其他函数/块(通常是闭包在语法上嵌套的函数/块)的局部变量。这样,局部变量的生存时间可以比它定义的块的寿命更长。当同一个变量有多个闭包时,它们可以使用该变量进行通信。
Java 的本地类(其中匿名类是一种特殊情况)支持此功能的有限版本:它们允许访问
final
变量,即不能更改其值的变量。这是通过将此变量的值复制到其构造时的本地类对象来实现的。您可以通过在此变量中使用可变对象(在最简单的情况下是单元素数组)来模拟真实的闭包。此外,Java 语法相当丑陋,但它与语言的其余部分很好地契合,并且允许静态类型安全(与所讨论的一些较短语法变体相反)。
I don't really know about the objective-C version of closures, but I know them from Smalltalk and Lua.
A closure is essentially a function which has access to a local variable of some other function/block (usually one in which the closure is syntactically nested). This way, the local variable can live longer than the block it is defined in. When you have multiple closures over the same variable, they can communicate using this variable.
Java's local classes (of which anonymous classes are a special case) support a limited version of this: They allow access to a
final
variable, i.e. a variable which can't change it's value. This is implemented by copying the value of this variable to the local class object on it's construction. You can emulate real closures by using a mutable object in this variable (in the simplest case a one-element array).Additionally, the Java syntax for this is quite ugly, but it fits in with the rest of the language nicely, and allows static type safety (contrary to some shorter-syntax variants which are discussed).