【问题标题】:Functional Programming vs OOP [closed]函数式编程与 OOP [关闭]
【发布时间】:2020-03-27 16:55:07
【问题描述】:

我刚刚查找了一些关于函数式编程和 OOP 之间差异的示例/定义。我发现了一个我认为很有趣的定义,并且我理解 OOP 部分,但需要对函数式编程部分进行一些清晰/示例。

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

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

【问题讨论】:

  • 你无法通过理解橙子来理解苹果。你仍然需要检查苹果。
  • 您能否详细说明此评论?我认为下面的回复和 cmets 有助于澄清我对原始陈述的理解
  • 您应该研究与 OOP 中的子类化和方法重载有很大不同的类型类/临时和参数多态性。您应该研究代数数据类型以及它们如何允许通过替代而不是 OOP 中的层次结构来构造数据。您应该考虑处理值之类的效果以及如何组合纯函数和不纯函数,而不是将消息从一个对象发送到另一个对象,等等。

标签: java scala oop functional-programming


【解决方案1】:

有一些核心实用函数确实让函数式编程感觉与众不同:mapfilterfold(也称为reduce)和unfold。此外,大多数函数式语言都使用这些操作可以针对的通用数据结构,并且数据由更简单的类型表示。而在面向对象的编程中,您可能有一个包含 Movie 对象的 MovieList 对象,并具有迭代或操作这些电影对象的方法,但您更有可能只拥有函数式语言中的 Movie 对象并在 List of Movie 数据结构的上下文中使用它们。

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

// This would, presumably, be a method on MovieList.
public List<String> getUppercaseTitles() {
    List<String> uppercaseTitles = new ArrayList<>();
    for (Movie movie : this.getMovies()) {
        uppercaseTitles.append(movie.getTitle().toUpper()); 
    }
    return uppercaseTitles;
}

在函数式语言中,类似的操作更可能如下所示:

uppercaseTitles :: [Movie] -> [String]
uppercaseTitles movies = map (toUpper . title) movies

换句话说,您不是使用for 循环和命令式方法调用来提供逐步指导,而是声明uppercaseTitles 由两个函数(toUpper 和@ 987654337@) 到电影列表。

【讨论】:

  • 我觉得你的例子有点虚伪,因为在你的比较中你选择了最糟糕的 OO 语言之一和最优雅的 FP 语言之一。例如,这会更公平。使用 Java 的 Stream API 作为您的 FP 示例,或者使用更好的 OO 语言。例如,在 Smalltalk 中,OO 示例如下所示:movies collect: [:movie | movie title asUpperCase ]
  • 我的意图不是选择“糟糕”的语言或“优雅”的语言。我追求的是概念的纯洁性,我认为带有命令式方法的“普通”Java 示例符合“OO 代码”的正常期望。我想避免像 Smalltalk 的 collect/inject 这样的东西,因为它们是高阶函数,所以我认为它们在这种情况下会令人困惑,因为它们本质上是“函数式”的。
  • 感谢您的回复......那么这是否意味着所有 FP 都包含某种形式的映射、过滤、折叠、展开方法?这本质上是一个必要条件吗(可能不是“官方”,但通常或多或少)
  • 是的,我会说这是一个基本的期望。我不知道任何没有这些的“功能性”语言。事实上,正如上面的讨论所示,大多数现代 OO 语言也采用了这些和其他功能性习惯用法 (including Java)。
  • 是的,这些以及其他高阶函数是 FP 语言的惯用语。它们通常命名相同,尽管它们可能有一些区别:map 可以是 collect;但filter 可以是selectrejectfold 可以是reduceinject。最基本的区别如答案所述:FP 偏向于对简单数据类型进行操作的函数,而 OO 则将数据类型和过程连接在一起。
【解决方案2】:

这是一种错误的二分法,因为函数式编程是关于如何组织计算,而 OO 是关于如何组织数据。

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

【讨论】:

  • 好的 - 所以 FP 可以同时拥有对象/类和函数,但主要区别在于如何有效地执行任务(FP 通过使用各种函数/方法更有效,而 OO 在通常通过使用对象/类来完成相同的任务)?
  • 我认为您确实将函数式编程与命令式编程进行了对比。在那个比较中,函数式通常更慢但更健壮;命令式更快但更容易出错。函数式编写也更快,更容易重用(假设两者的技能水平相同)。
【解决方案3】:

我认为它可以帮助您看到简单的区别,您可以查看 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.

您只使用一种方法 - count()。 通过这种方式,您可以避免方法重复,只需使用功能方式来操作您需要的东西。无论如何,由于泛型,您将返回对象(不是原始变量)。

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-10-06
    • 2023-03-21
    • 2010-10-06
    • 2010-09-22
    • 2013-01-29
    • 2011-04-17
    • 2018-04-23
    • 2011-11-16
    相关资源
    最近更新 更多