为什么Java没有方法委托?

13

Java的卓越大师们(gurunaths,natha नाथ = 梵文中的神灵-大师-保护者)应该降低身段接受委托的必要性,并将其纳入Java规范。

在C#中,我可以将方法作为处理程序传递,引用为委托,而无需因需要传递方法而创建类。但在Java中不行。

除了引用全新类以外的笨拙使用外,Sun决定不将委托引入Java的原因是什么?在匿名创建类或实现接口方面,与委托相比有哪些优势?我想不到任何优势,你呢?


6
我更新了你的问题标题,因为“Java should have method delegates”听起来不太好。 - Bozho
许多人越来越认为他们在一开始没有代表参与是犯了一个大错误。有些人说,即使有了代表也会是一个错误,没有人应该认为函数是二等公民。 - balpha
@bozho 如果你要更改某人的帖子标题,你应该非常注意语法。我不是要成为一个语法纳粹,但你会让他看起来很糟糕(尽管你的编辑意图是好的)。 - Rob Fonseca-Ensor
当我编辑某些东西时,我会用评论指出来,以便明显表明这是我的“错误” :) - Bozho
9个回答

15

首先,我并不反对或支持向Java中添加委托。我只是在解释背景。

其次,相较于C#团队,Sun的Java团队传统上更加保守,不太愿意让语言进化。

第三,将委托结构添加到Java中可能需要引入新的关键字,比如“delegate”。这将破坏现有代码中已经存在的名为“delegate”的变量。

第四,有一个设计原则叫做“单一选择原则”http://en.wikipedia.org/wiki/Single_choice_principle。当应用于语言设计时,意味着程序员只应有一种明显的方法来实现某个目标。换句话说,多种选择是有风险的。向Java中添加委托将违反这一原则,因为它们的行为可以通过匿名类来实现。

[当然,这个原则不应被字面理解。如果是这样的话,我们就要使用好老的图灵机来编程了。我想Sun的团队认为,委托并没有超过单一选择违规的好处]


1
对于“单一选择原则”,我给予了+1的认可。我一直很欣赏Java工件的简洁性以及它的字节码表示。你表达了这个想法,非常好。 - Chandra Patni
1
如果是这样的话,我们将会使用一个好老式的图灵机进行编程。实际上,图灵机从未被视为一种实用的硬件模型或编程模型。它的真正目的是作为计算理论中证明某些数学结果的模型。 - Stephen C
1
您可以添加上下文敏感的关键字,而不会破坏现有代码(或者只需使用foreach循环中的冒号这样的高级运算符),以便在不可能添加关键字的情况下进行操作。 - akuhn
1
我认为Java团队更加保守,因为他们经营的时间更长。向后兼容性一直是他们的首要任务。也许他们比微软所拥有的忠实用户更加重视此项任务。 - duffymo

15

这里是汤姆·鲍尔关于微软建议将它们添加到Java以及Sun为什么拒绝它们的账户。

我认为Java应该在十二年前就有闭包了。吉拉德·布拉哈主张使用闭包,但没有人听取。用他自己的话说:

我个人从1997/98年开始就主张添加闭包。当我回想起当时得到的回应:“我们的客户不需要它,为什么要添加呢?”时,我的血压仍然会明显上升。

可悲但事实。


@eaglestorm - 你能否提供一份你评论的备份? - 5StringRyan
官方Sun立场(http://java.sun.com/docs/white/delegates.html)与J++有关,我认为Gosling本人也在某处发表了一篇文章。 - eaglestorm
现在Java也有闭包了,它叫做Groovy :) - eaglestorm
@Moshe Itay和Mehrdad提供了为什么这不是一个好主意的很好的解释。所以你是说你比整个Sun Java开发团队都更懂? - eaglestorm
1
@eaglestorm,按照你的逻辑,Microsoft或Sun/Oracle都不知道自己在做什么?等待半个世纪才进行这些“非常必要”的增强措施,这就是你的解决方案吗...?Java平台现在已经过时了。 你可以尽情地讨论这些决定背后的理念,但实际上,自从.NET 3.5问世以来,在.NET平台下进行开发要容易得多。 - Moshe Bixenshpaner
显示剩余4条评论

6

简洁性。

Java没有引入委托的概念,这使得语言更加简单。就像没有属性、索引器等一样。

(顺便说一句,使用简单的语言不一定更简单;也许他们应该添加委托,但这并不是他们做出设计决策的方式)


3
没有委托使我的项目变得复杂且臃肿,到处都是匿名类和不必要的接口。 - Blessed Geek
2
@h2g2java:在我纯个人的观点中(免责声明:我的最爱语言是C#),我同意你的看法,认为Java被设计得过于“纯粹”。他们为了语言的纯洁和简单性而牺牲了太多的易用性。然而,有些人(比如设计者)肯定不同意。毕竟,设计一种语言很难,你必须做出很多权衡。如果你向一种语言添加任何可能的功能,你最终会重新发明C++ ;)。 - Mehrdad Afshari
3
也许一个纯粹的面向对象设计并不是解决问题的最佳方式,而函数式编程范式可能更加有效。毕竟,面向对象编程原则的终极目标是创造更好的软件,而不是盲目地遵循这些原则。 - Mehrdad Afshari
2
这是相当正确的,但也许使用函数式技术看起来像是“简单的路径”,而真正使软件在可维护性、可读性和稳定性方面变得更好的路径则在面向对象编程领域中;或许需要一个设计模式。 - Bozho
再次澄清一下,我的意思是,如果你问设计师的话,他们可能会提出“简洁”和“纯净”的论点。是的,我也认为他们错了,没有加入它是一个错误。 - Mehrdad Afshari
显示剩余3条评论

4

Java没有闭包,因为它的设计初衷不是作为一种函数式语言,而是面向对象的语言。
在许多情况下,您可以模拟另一种语言范例,例如使用匿名接口代替闭包。
但现在情况正在发生变化,在新的JVM语言(如Scala、Groovy、JRuby等)的压力下,这些语言结合了面向对象和函数式范例,Java委员会正在尝试将闭包放入Java 7中。


我相信在一些委员会的犹豫之后,闭包现在将进入Java 7。 - Brian Agnew

2
在Java中,您有内部类,它们与父类的一个特定实例相关联,并直接访问其成员。因此,实现内部类不需要(太多)比编写方法更多的代码。
C#没有内部类。无论是像Java中的内部类还是像C#中的委托,它们都有各自的优点(有时我会在C#中想念内部类),但从语言设计者的角度来看,坚持其中一种是有道理的(而不是支持两种),因为这使得类库设计更加一致。

但是在C#中,您可以拥有嵌套类,并且它们也可以访问其父类的私有成员。 - vgru
@Groo:据我所知,不会。嵌套类(C#)不会自动获得对父类的引用。您应该显式传递它。 - bohdan_trotsenko
1
没错。嵌套类 != 内部类。C# 中的嵌套类对应于 Java 中的“静态嵌套类”;请参阅我回答中“内部类”后面的链接。 - Heinzi

1

因为他们认为:

绑定方法引用[委托]是完全不必要的。此外,它们会削弱Java语言的简洁性和统一性。绑定方法引用并不是未来语言发展的正确方向。

摘自这份(旧的)白皮书:

http://java.sun.com/docs/white/delegates.html

现在Java正在考虑添加它们,一旦语言发展到足够的程度。我相信它们很快就会成为语言的一部分(至少比Perl 6更快:P)

您还可以使用:软件猴回调方法


0

也许是因为如果一个方法要被传递和共享到多个对象中,它就不应该由单个类拥有。它可能应该通过自己的类进行共享。我的意思是,如果你考虑一下,一个短暂的函数确实感觉有点奇怪。我想这是不好的面向对象编程。

我真的很喜欢使用委托来处理UI工作。这使得窗口操作变得更加容易编程。

这可能取决于你认为哪个更负面,一个具有错误所有者的函数,还是(至少在我的情况下)你的代码具有属于一个类的方法(按钮点击、窗口调整大小事件),而这些方法并不属于那个类。

我不确定我更喜欢哪一个。


0

不管价值如何,我已经使用反射在Java中实现了回调/委托支持。详细信息和可工作的源代码可以在我的网站上找到。


-2

C#中的委托对我来说看起来很丑。(将某些东西声明为变量,然后在其后添加()在面向对象编程中感觉不好)

此外,如果您想要:"委托对象可以传递给可以调用引用方法的代码,而无需在编译时知道将调用哪个方法。

您可以简单地使用java.lang.reflect.Method

编辑:正如您所说,使用反射不是一个好的方法。这是真的,但是在面向对象编程的角度来看,使用委托也不是更好的方法,我认为它是一种函数式语言结构。


如果您因为“丑陋”一词而对此进行了负投票,请告诉我,我会将其更改为“不美丽” ;) - Bozho
4
我没有给任何人投反对票,但我们都知道反思应该是最后的手段。 - Blessed Geek
我同意这一点,但它和委托一样缺乏面向对象编程的特性。 - Bozho
1
许多其他编程语言将函数视为对象,因此将方法签名声明为类型不应被视为不好的面向对象编程。这就像说当您需要多个属性时,不喜欢Fortran变量名称前的:: - Cecil Has a Name
Java也将_methods_视为对象,正如我在我的答案中所指出的。但是过度依赖它们并不是一个好习惯。 - Bozho

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接