Java 函数式编程与面向对象编程

Java 函数式编程与面向对象编程,java,scala,oop,functional-programming,Java,Scala,Oop,Functional Programming,我只是查阅了一些函数式编程和面向对象编程之间差异的示例/定义。我找到了一个我认为很有趣的定义,我理解OOP部分,但需要对函数式编程部分进行一些澄清/示例 “函数式编程倾向于重用一组通用的函数式实用程序来处理数据。面向对象编程倾向于将方法和数据集中在对象中。” 什么是功能实用程序?一般来说,我得到OOP,所以这个定义对我来说是有意义的。提前感谢有几个核心实用程序函数真正让函数式编程感觉不同:映射,过滤,折叠(也称为减少),和展开。此外,大多数函数式语言使用这些操作可以针对的通用数据结构,并且数据由

我只是查阅了一些函数式编程和面向对象编程之间差异的示例/定义。我找到了一个我认为很有趣的定义,我理解OOP部分,但需要对函数式编程部分进行一些澄清/示例

“函数式编程倾向于重用一组通用的函数式实用程序来处理数据。面向对象编程倾向于将方法和数据集中在对象中。”


什么是功能实用程序?一般来说,我得到OOP,所以这个定义对我来说是有意义的。提前感谢

有几个核心实用程序函数真正让函数式编程感觉不同:
映射
过滤
折叠
(也称为
减少
),和
展开
。此外,大多数函数式语言使用这些操作可以针对的通用数据结构,并且数据由更简单的类型表示。而在面向对象编程中,您可能有一个
MovieList
对象,该对象包含
Movie
对象,并具有迭代或操作这些Movie对象的方法,您更可能只使用函数式语言中的
Movie
对象,并在Movie数据结构的
列表的上下文中使用它们

例如,假设您想要一个OO语言的电影标题的大写版本。它可能看起来像这样:

//这可能是MovieList上的一个方法。
公共列表getUppercaseTitles(){
List uppercaseTitles=新的ArrayList();
for(电影:this.getMovies()){
append(movie.getTitle().toUpper());
}
返回大写标题;
}
在函数式语言中,类似的操作更可能如下所示:

大写标题::[Movie]->[String]
大写字幕电影=地图(toUpper.title)电影

换句话说,您不是用
为循环和命令式方法调用提供一步一步的指示,而是声明
uppercaseTitles
由两个函数组成的
map
toUpper
title
)这是一种错误的二分法,因为函数式编程是关于如何组织计算,而OO是关于如何组织数据


Scala是一个很好的例子,说明了这两个人是如何愉快地坐在一起的。它具有强大的功能特性,可以轻松地创建和组合函数作为第一类对象。它还有一个类系统,可以很容易地创建将数据与对该数据进行操作的函数相结合的对象。

我认为它可以帮助您看到简单的区别,您可以查看Java示例

您可以使用经典方式创建方法:

public int multiply(int a, int b, int c){
return a * b * c;
}
public int sum(int a, int b, int c){
return a + b + c;
}
但您可以以功能性的方式实现它:

@FunctionalInterface
interface Operation<T, R> {
    T count(R a, R b, R c);
} // or you can use Java 8 functional interfaces, if its usefull for you.

Operation<Double, Integer> divide= (x,y,z) -> x / y / z;
sout(divide.count(12,4,5); // returns quotient in Double type.
Opertion<Integer, Integer> sum = (x,y,z) -> x + y + z;
sout(sum.count(1,3,3) // returns sum in Integer type.
@functioninterface
接口操作{
T计数(ra,rb,rc);
}//或者,如果Java 8功能接口对您有用,您也可以使用它。
运算除法=(x,y,z)->x/y/z;
sout(divide.count(12,4,5);//返回双精度类型的商。
运算和=(x,y,z)->x+y+z;
sout(sum.count(1,3,3)//返回整数类型的sum。
您只使用一个方法-count()。 通过这种方式,您可以避免方法的重复,并且只使用函数方式来操作所需的内容。无论如何,由于泛型,您会得到返回的对象(而不是原始变量)


但是函数式编程还不清楚。如果你精通Java,你可以试试Scala(但也不清楚函数式语言。函数式语言的好例子有:Haskell、JavaScript、PureScript

我觉得你的例子有点不真实,因为你在比较中选择了最差的OO语言之一和最优雅的FP语言之一。例如,使用Java的
API作为例子会更公平。)我们的FP示例,或者使用更好的OO语言。例如,在Smalltalk中,OO示例看起来是这样的:
movies collect:[:movie | movie title asupercase]
。我的目的不是选择一种“糟糕”的语言或“优雅”的语言。我追求的是概念的纯粹性,我认为“简单”Java示例及其命令式方法符合“OO代码”的正常期望。我想避免使用Smalltalk的
收集
/
注入
,因为这些都是高阶函数,所以我认为它们在这种情况下很容易混淆,因为它们是“功能性的”在自然界中。感谢您的回答……那么这是否意味着所有FP都包括某种形式的映射、过滤、折叠、展开方法?这本质上是一个必要条件(可能不是“正式的”,但大体上或多或少)是的,我会说这是一个基本期望。我不知道有任何“功能性的”没有这些功能的语言;事实上,正如上面的讨论所示,大多数现代OO语言也采用了这些和其他功能性习惯用法()是的,这些函数和其他高阶函数是FP语言的惯用函数。它们的名称通常是相同的,尽管它们可能有一些不同:
map
可以是
collect
;但是
filter
可以是
select
reject
fold
可以是
reduce
inject
。最基本区别如回答中所述:FP支持在简单数据类型上操作的函数,而OO将数据类型和过程连接在一起。好的-因此FP可以同时拥有对象/类和函数,但主要区别在于如何高效地执行任务(FP通过使用各种函数/方法更有效,而OO通常通过使用对象/类在同一任务中更有效)?我认为您确实在将函数式编程与命令式编程进行对比。在这种对比中,函数式编程通常较慢,但更健壮;命令式编程更快,但更容易出错。函数式编程也更快地编写和执行