无状态面向对象编程与函数式编程?

Posted

技术标签:

【中文标题】无状态面向对象编程与函数式编程?【英文标题】:Stateless Object Oriented Programming vs. Functional Programming? 【发布时间】:2011-11-16 06:15:09 【问题描述】:

如今,越来越多的注意力转向函数式编程的主要原因之一是多线程/处理的兴起,以及 FP 专注于无副作用、无状态计算的优势,从而使可扩展性变得轻松。

当然,尽管如此,在面向对象编程中,我们也可以转向无状态范式,在这种范式中,所有对象都不会改变状态。这可以是一种约定,甚至可能是语言隐式支持的。例如,在强制对象字段和方法之间统一访问的语言中,简单地不允许 setter 方法就可以实现这一点。

那么,我的问题是,既然 OO 可以利用无状态性,而对象没有任何要求有状态性,那么 OOP 是否实际上是 FP 的超集? FP 是否有任何其他优势/特性使多线程比 OOP 更实用?

【问题讨论】:

我希望那些无理由投票关闭的人被收取 5000 名声望。绝对是我最不喜欢的组。 这种 OO 只是 FP 的一个非常有限的子集(假设不满足其他 FP 要求,例如一流的函数和闭包)。您希望从这样的 OOP 中获得什么样的消息语义?不修改对象状态的消息是纯函数。然后类将成为模块。 当然,在这一点上,我不认为一流的函数和闭包是一个严格的函数特性(尽管这是它们开始的地方)。许多面向对象的语言可以通过块或类似机制支持闭包。我也在谈论禁用可变性,而不是实例化。可以遵循函数式编程中使用的相同模式,其中通过动态创建新对象及其组合对象来组合不可变原语来模拟修改状态。 @SK-logic 关于方法成为函数的假设是完全错误的——它们仍然可以访问类中的最终数据并且仍然表现出封装和继承。这实际上是 OO 编程的最佳方式。 @Bill K,他们能读到什么并不重要——只要他们不能修改状态,它们就是纯函数。而且,适当的模块提供了比典型 OOP 更好的封装——例如,查看 SML 第一类模块。 【参考方案1】:

FP 更多的是关于你解决问题的方式,而不是你使用的语言。所以没有 OOP 不是 FP 的超集。 FP 中的某些构造(mapReduce,...)可以隐式转换为多线程应用程序。但是没有什么能阻止您在 OOP 中使用它们。一切都与心态有关。

【讨论】:

【参考方案2】:

这是学位的问题。

使用函数式语言进行函数式编程的好处是胡萝卜加大棒。胡萝卜是函数式语言具有函数式语法和语义,并带有函数库。关键是函数式语言可以迫使您遵守某些标准。如果你用非 FP 语言做 FP,你就不会得到这些。您必然会与对状态友好的标准库作斗争,并且必须自我监督以确保您不会创建状态。

在 C 中做 OO 的类比是一个很好的类比。有时您的约束条件使得 C 是正确的选择,而 OO 结构也是正确的选择。 GTK 就是一个很好的例子。如果没有 OOP,很难编写 UI 工具包。但是,这意味着您正在承担通常由编译器完成的工作。如果没有句法和语义支持,一些在一种语言中很容易的事情在一种语言中变得困难或不可能。例如,我从未见过模拟多重继承的 C 项目。实在是太费体力了。

如果您为了并行性而在您的 OO 代码中采用函数式风格,那么您很可能会在不费吹灰之力的情况下获得您所追求的好处。但是您仍然会错过编译时保证,即您的代码是纯的、对 FP 的语言内支持以及 FP 编译器如今能够进行的令人印象深刻的优化。这是一个权衡,所以这是一个必须根据具体情况做出的决定,而且只有你可以做出。

至于 OOP 是否是 FP 的超集,我什至认为这个概念没有意义。在表达程序方面,他们都是完全有能力的。您可以在 FP 语言中实现 OO 语言,反之亦然。有时一个更接近问题域,有时另一个。无论如何,我认为你真正的问题是是否一定要喜欢 FP,答案是,不;用你喜欢的。

我认为您还应该考虑检查 Actor 模型,因为它更适合 OO 而不是状态不友好(只是共享状态不友好),同时仍然产生可扩展性/并行性优势。

【讨论】:

非常好的点。有点无关紧要,但实际上我个人非常同意“没有 OOP 很难编写 UI 工具包”的说法,但是我们有 JQuery(不过,这是另一天的争论 :))。我也听说过很多关于 Actor Model 的事情,我很想看到更多可用的库来实现这个。总而言之,线程在状态不被隔离的环境中似乎太低级了,因此任何解决方案,无论是存在抽象以使线程安全变得容易的有状态范式,还是自动使其变得容易的无状态范式,都应该受到欢迎 关于 jQuery,它本身只修改 DOM,这已经是 OO。除非您使用 jQuery UI——它引入了“widget”对象,否则它不会带来任何新的小部件。 :)【参考方案3】:

我曾经有过同样的理解,并且被“更正”了。我不是一个函数式的人,我不明白,但显然函数式语言中有一些工具可以更好地适应这种编程风格。

我认为这就像一个 C 程序员说的,既然 C 方法可以组合成一个结构并被替换,那不是让 C 成为 OO 的超集吗?事实上,这就是 C++ 最初的实现方式,但它并没有使 C 成为一种 OO 语言。

【讨论】:

我认为你是对的,也许“超集”不是正确的术语。最后,我们谈论的是不同的范式。我想我想看看 OO 和 FP 范式最终是否真的很相似,其中 OO 与 FP 范式非常相似,但额外考虑了状态。 @donalbain,OO 不能与 FP“相似”。这是完全不同的。没有诸如 OOP 的指称语义之类的东西。 OOP 不是一个完整的范式,它只能与一些完整的语义一起使用。 这绝对不是我熟悉的领域。如果我没有误解指称语义,这里我们讨论的是证明程序在数学上正确的方法吗? @donalbain,不,这是关于程序的执行方式。 OOP 基本上只是一个类型系统,它没有定义任何关于底层评估模型的内容。另一方面,FP 什么都不是,它只是一种评估模型,可以与多种类型系统结合使用。

以上是关于无状态面向对象编程与函数式编程?的主要内容,如果未能解决你的问题,请参考以下文章

Scala学习(函数式编程面向对象编程)

Scala学习(函数式编程面向对象编程)

函数式编程与面向对象编程[5]:编程的本质

函数式编程与面向对象编程[关闭]

面向对象

为什么说面向对象编程和函数式编程都有问题