静态方法使Java成为伪函数式语言?

时间:2009-02-25 07:19:46

标签: java closures functional-programming

我一直在考虑Misko Hevery的post,Java中的静态方法是死于可测试性。我不想讨论可测试性问题,而是讨论静态方法的概念。为什么人们如此讨厌它?

确实,我们没有闭包(但我们有一个稍微尴尬的匿名函数),lambdas&作为第一类对象。在某种程度上,我认为静态方法可以用来模拟作为第一类对象的函数。

6 个答案:

答案 0 :(得分:4)

静态方法使测试变得困难,因为它们无法替换,就像那样简单。

静态方法如何“模仿”作为第一类对象 1 ?可以说,他们在这方面比其他任何事情都要糟糕。您可以通过创建单方法接口来“模仿”作为第一类对象的功能,事实上Google的Java Collections在许多地方(对于谓词,投影等)都是这样做的。静态方法无法做到 - 除了反射之外没有办法传递“当你想要应用函数时,使用这个方法。”

不,我看不到静态方法如何帮助。它们阻止状态改变(因为唯一可用的状态是全局状态和通过参数传递的任何可变状态)但它们对“作为第一类对象的功能”方面没有帮助。

C#拥有更好的支持(使用lambda表达式和委托),但即使这样也不像它那样普遍。 (例如,将它与F#进行比较。)


1 从Java 8开始,方法引用将允许将方法转换为适当的单方法接口的实例,这将使所有更多相关。早在2009年,这还有很长的路要走......

答案 1 :(得分:3)

功能!=功能,对于记录我会声称方法!=功能......

Java是一种静态类型的,面向对象的语言。 Java也以这种方式保持了相对的纯度,但它并没有接近函数式语言。

虽然你可以通过命令式编程来模仿函数式编程的行为,但你永远不会得到那些你想要用于lambda演算的整洁语法。在某种程度上,如果语言不支持正确的lambda演算,那么它就不是函数式编程语言。

C ++有函数,但C ++也有类。因此,C ++有两种类型的函数,成员函数和函数。当你说方法时,你指的是一个成员函数。因为该方法是在对象的实例上调用的。但是当你说静态方法时,你的意思就是函数(在C / C ++意义上)。这只是一个用于引用代码元素的词汇表。并且在Java代码中不能存在于类之外,一种方法意味着它属于某种类,即类型。

到目前为止,我所说的与函数式编程无关,但我认为你明白你错了。

我建议你看一下纯函数式编程语言,比如Haskell或Erlang。因为函数式编程语言通常也没有闭包器。

你声称静态方法可以用来模仿作为头等对象的函数听起来很奇怪。它听起来更像是一种动态编程语言,而不是函数式编程。

答案 2 :(得分:3)

函数式编程的一个特征是数据的不变性。 static确实意味着您不需要表示状态的对象(实例),因此这不是一个糟糕的开始。但是,您在课程级别上有状态,但您可以创建此final。由于(静态)方法根本不是第一类函数,因此您仍然需要像匿名类这样的丑陋构造来接近Java中函数式编程的某些样式

FP最好用函数式语言完成,因为它具有必要的语言支持,用于高阶函数,不变性,引用透明度等等。

但是,这并不意味着您无法使用Java等命令式语言编写功能样式。其他例子也可以给出。这不是因为您使用Java进行编程而是在进行OOP。您可以使用结构化语言(如C ++)对全局数据和非结构化控制流(goto)进行编程。我可以用函数式语言来做OOP。等

Steve McConnell提到了语言中编程编程 Code Complete中的语言(也是SO上非常流行的参考文献)的区别。

所以,简而言之,如果你说“静态方法模仿一流的功能”,我不同意。

但是,如果我认为这更像是你试图解决的问题,你会说“静态方法可以帮助用Java编写功能样式”,我同意。

答案 3 :(得分:0)

我对静态方法的最大反对意见是它们不是多态的,并且它们不是以面向对象的方式使用,而是一个人必须让你的类(不是对象)来访问它们。

答案 4 :(得分:0)

如果您只使用静态方法,那么您将使用过程式,非面向对象的方式进行编程。

然而,在我介绍面向对象之前的第一个编程课程中,我能想到的唯一情况就是这样。

答案 5 :(得分:0)

在Java中,你不能将函数作为另一个函数的参数。

在函数式语言中,如果你有一个函数

def addOne(i) = i + 1

你可以将它传递给另一个函数,例如将它应用于列表的所有元素。

在Java中,使用

public static int addOne(int i) { return i + 1; }

没有办法做到这一点。