简体   繁体   English

Java 匿名类与 Objective-C 块相比的限制

[英]Limitations of Java Anonymous Classes compared to Objective-C Blocks

I'm just starting to wrap my head around first order functions and closures after discovering blocks in Objective-C.在发现 Objective-C 中的块后,我才刚刚开始关注一阶函数和闭包。 Java is another language where I've heard about closures (or lack thereof) and how anonymous classes make up for this somewhat. Java 是另一种我听说过闭包(或缺少闭包)以及匿名类如何弥补这一点的语言。

I can definitely see the advantages of closures as blocks in Objective-C, but what are the limitations of anonymous Java classes?我绝对可以在 Objective-C 中看到闭包作为块的优势,但是匿名 Java 类的限制是什么? To what extent do they 'somewhat' make up for the lack of true closures?它们在多大程度上“在某种程度上”弥补了真正关闭的不足?

Java anonymous classes are really, really wordy. Java 匿名类真的非常罗嗦。 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.除了定义它们所需的大量样板之外,Java 的一些设计决策意味着许多常见任务比其他语言更冗长。 For example, importing mutable upvalues into the closure is a pain in the arse in Java.例如,在 Java 中,将可变上值导入闭包是一件很麻烦的事情。

Basically, Java doesn't support upvalues;基本上,Java 不支持升值; instead they're simulated by passing them (by value) into the class via invisible parameters to the class's constructor.相反,它们是通过将它们(按值)传递到 class 通过类的构造函数的不可见参数来模拟的。 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.因为它们是按值传递的,所以在 class 中修改它们不会影响构造 class 的方法中的副本,因此编译器会让您将它们声明为 final 以避免混淆自己。 eg:例如:

Runnable function()
{
   final int i = 4;
   return new Runnable()
   {
       public void run()
       {
            System.out.println("i="+i);
            // can't modify i here
       }
   }
}

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:在您确实需要修改变量的情况下,例如在几乎所有闭包有用的情况下,您必须作弊:

Runnable function()
{
   final int[] i = new int[1];
   i[0] = 4;
   return new Runnable()
   {
       public void run()
       {
            System.out.println("i="+i[0]);
            i[0] = i[0] + 1;
       }
   }
}

Here, i itself is still immutable, but because it points at a mutable object, I can change the contents of the object.在这里, i本身仍然是不可变的,但是因为它指向一个可变的 object,所以我可以更改 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.) (当然,在现实生活中,我会使用 class 而不是数组,因为使用 arrays 真的很难看。这使它更加罗嗦。)

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.我推测下一个 Java 版本将包含语法糖以使这一切变得更容易,但现在在 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.我发现更改逻辑不使用闭包通常更容易,只是为了让我保持使用中的代码量足够小以易于理解。

I don't really know about the objective-C version of closures, but I know them from Smalltalk and Lua.我不太了解 objective-C 版本的闭包,但我从 Smalltalk 和 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).闭包本质上是一个 function ,它可以访问其他一些函数/块的局部变量(通常是闭包在语法上嵌套的一个)。 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, ie a variable which can't change it's value. Java 的本地类(其中匿名类是一个特例)支持这种限制版本:它们允许访问final变量,即不能更改其值的变量。 This is implemented by copying the value of this variable to the local class object on it's construction.这是通过将此变量的值复制到其构造上的本地 class object 来实现的。 You can emulate real closures by using a mutable object in this variable (in the simplest case a one-element array).您可以通过在此变量中使用可变的 object 来模拟真正的闭包(在最简单的情况下是单元素数组)。

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).此外,Java 的语法非常难看,但它很好地符合该语言的 rest,并允许 static 类型安全性(与某些较短的语法变体相反)。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM