功能编程与面向对象编程

时间:2010-01-16 21:35:49

标签: oop functional-programming paradigms

到目前为止,我已经主要接触过OO编程,并期待学习一门函数式语言。我的问题是:

  • 您何时选择面向对象的函数式编程?
  • 函数式编程是更好的选择的典型问题定义是什么?

4 个答案:

答案 0 :(得分:1140)

  

何时选择面向对象的函数式编程?

当您预料到不同类型的软件演变时:

  • 当您在的东西上有一组固定的操作时,面向对象的语言是很好的,随着您的代码的发展,您主要添加新的东西。这可以通过添加实现现有方法的新类来实现,并且现有类是独立的。

  • 当您拥有一组固定的内容时,功能语言会很好,并且随着代码的发展,您主要在现有内容上添加新的操作。这可以通过添加使用现有数据类型计算的新函数来实现,并且现有函数不受影响。

当进化走向错误时,你就会遇到问题:

  • 向面向对象的程序添加新操作可能需要编辑许多类定义以添加新方法。

  • 在功能程序中添加新类型的东西可能需要编辑许多函数定义来添加新案例。

这个问题多年来一直众所周知; 1998年,Phil Wadler dubbed it the "expression problem"。虽然一些研究人员认为表达问题可以通过mixins这样的语言特性来解决,但是一种被广泛接受的解决方案尚未成为主流。

  

函数式编程是更好的选择的典型问题定义是什么?

功能语言擅长以树形式处理符号数据。最喜欢的例子是编译器,其中源语言和中间语言很少变化(大多数是相同的 thing ),但编译器编写者总是添加新的翻译和代码改进或优化(对事物的新操作)。编译和翻译通常是功能语言的“杀手级应用程序”。

答案 1 :(得分:167)

您不一定要在两种范例之间进行选择。您可以使用许多功能概念编写具有OO架构的软件。 FP和OOP本质上是正交的

以C#为例。你可以说它主要是OOP,但有许多FP概念和结构。如果你考虑 Linq ,允许Linq存在的最重要的结构本质上是功能性的: lambda表达式

另一个例子,F#。你可以说它主要是FP,但有许多OOP概念和结构可用。您可以定义类,抽象类,接口,处理继承。您甚至可以在使代码更清晰或显着提高性能时使用可变性。

许多现代语言都是多范式的。

推荐读物

由于我在同一条船上(OOP背景,学习FP),我建议你阅读一些我非常感激的读物:

答案 2 :(得分:31)

面向对象编程提供:

  1. 封装,到
    • 控制内部状态的突变
    • 限制与内部代表的耦合
  2. 子类型,允许:
    • 替换兼容类型(多态)
    • 在类之间共享实现的粗略方法(实现继承)
  3. 在Haskell甚至Scala中,函数式编程可以允许通过更一般的类型类机制进行替换。不鼓励或禁止可变的内部状态。还可以实现内部表示的封装。请参阅Haskell vs OOP进行比较。

    Norman断言“在功能程序中添加新东西可能需要编辑许多函数定义来添加新案例。”取决于功能代码使用类型类的程度。如果特定抽象数据类型上的模式匹配遍布整个代码库,您确实会遇到这个问题,但这可能是一个糟糕的设计。

    已编辑在讨论类型类时删除了对隐式转换的引用。在Scala中,类型类使用隐式参数进行编码,而不是转换,尽管隐式转换是实现兼容类型替换的另一种方法。

答案 3 :(得分:23)

  1. 如果您处于高度并发的环境中,那么纯函数式编程非常有用。缺乏可变状态使得并发几乎是微不足道的。见Erlang。

  2. 在多范式语言中,如果可变状态的存在必须是实现细节,您可能希望在功能上对某些事物进行建模,因此FP是问题域的良好模型。例如,请参阅Python中的列表推导或D编程语言中的std.range。这些都受到函数式编程的启发。