OOP与函数式编程与过程性[关闭]


237

这些编程范例之间有什么区别,它们是否更适合于特定问题,还是任何用例都比其他用例更受青睐?

欣赏建筑实例!


这不是一个完整的答案,但是我在这里写了一些有关“功能”如何影响/对比“ OO”样式(在F#的情况下)的信息:lorgonblog.spaces.live.com/blog/cns!701679AD17B6D310!511。参赛作品
布赖恩

您可以考虑阅读本文!有很多例子说明何时使用哪种蚂蚁,主要区别是什么,优点/缺点等
Nikita Ignatov,2009年



鲍伯叔叔在推特上发了这件事。还有这里
jaco0646

Answers:


129

他们每个人都有自己的优点-它们只是解决相同问题的不同方法。

在纯粹的过程样式中,数据往往与对其上运行的功能高度去耦。

在面向对象的样式中,数据倾向于带有一系列功能。

在功能样式中,数据和功能趋向于彼此之间有更多的共同点(如Lisp和Scheme),同时在实际使用功能方面提供了更大的灵活性。还倾向于根据递归和组合而不是循环和迭代来定义算法。

当然,语言本身只会影响首选哪种样式。即使使用像Haskell这样的纯函数式语言,也可以以过程样式(尽管不鼓励这样做)编写,甚至可以使用像C这样的过程语言,以面向对象的样式(例如GTK +和EFL API)。

需要明确的是,每个范例的“优势”仅在于算法和数据结构的建模。例如,如果您的算法涉及列表和树,那么功能性算法可能是最明智的。或者,例如,如果您的数据是高度结构化的,则如果这是您语言的本机范式,则将其组合为对象可能更有意义-或者,可以将其作为monad的功能抽象一样容易地编写,是Haskell或ML之类的语言的原生范例。

您选择使用哪种方法,对您的项目和语言支持的抽象才更有意义。


5
您所说的似乎并不反映您所写的内容。您说他们没有“利弊”,然后说他们是不同的方法。为什么有人会根据任何给定情况选择一种方法而不是另一种方法?优点和缺点,优点和缺点,无论您怎么说,它们的确存在!我并不是说一个人本质上会更好,您也没有。我相信那是您真正想说的。除非您真的相信任何选择的方法相对于另一种方法都没有正面和负面的影响。
JM Becker

1
@TechZilla:我同意我的措辞很差,但是我的意思是,实际上并没有列出可以指向的语言,并且说X语言比Y语言更好,而又没有证明X语言更适合编写算法U和语言的情况。 Y可能更适合编写算法V,而两者都可以轻松地用两种语言实现。
greyfade 2011年

2
程序和功能之间的区别对我来说还不清楚。我在大学学习Scheme / Rackett,但是我真的看不到它与过程C或PHP之间的巨大区别,您能举个例子吗?
莱昂内尔

7
@Leonel:大多数人会引用的最大区别是,在过程语言中,您可能会使用for循环,但在功能语言中则没有这种东西-相反,您使用对函数的递归调用来执行相同的任务。函数式语言也使函数成为一流的对象-您可以像传递数字一样将它们传递给对象-但您无法在C语言中做到这一点(并且PHP对它的支持已被破坏)。
greyfade

2
@tastro:当一种范例比另一种更有意义时。这就是全部。有时,将代码建模为功能的组合更有意义,有时,将数据建模为对象更有意义。有很多表达算法和数据结构的方法。OOP和功能恰好是其中的两个。
greyfade 2014年

25

我认为这些天可用的库,工具,示例和社区完全取代了范例。例如,ML(或其他任何语言)可能是最终的通用编程语言,但是如果您无法为正在做的事情获得任何好的库,那么您就搞砸了。

例如,如果您要制作视频游戏,那么C ++中会有更多优秀的代码示例和SDK,因此您可能会更好。对于小型Web应用程序,有一些很棒的Python,PHP和Ruby框架可以使您快速启动并运行。由于编译时检查以及企业库和平台,Java是大型项目的理想选择。

过去的情况是,用于不同语言的标准库很小并且易于复制-C,C ++,Assembler,ML,LISP等。这些库具有基础知识,但是当涉及到事物标准化时,往往会遇到麻烦像网络通讯,加密,图形,数据文件格式(包括XML),甚至基本的数据结构(如平衡树和哈希表)都被忽略了!

如今,Python,PHP,Ruby和Java等现代语言都提供了更为完善的标准库,并且您可以轻松使用许多优秀的第三方库,这在很大程度上要归功于它们采用了命名空间来防止库相互冲突,和垃圾回收,以标准化库的内存管理方案。


5
Python,ruby等没有像C或LISP这样的“标准”库,因为它们是单一的实现语言。Guido所说的是Python,没有标准。如今,任何特定的C或LISP(或其他)实现都带有标准库以外的大量库。
Dan Andreatta 2010年

8
问题在于面向对象,功能和过程编程之间的差异。虽然这些答案中提到的语言肯定适合其中一种方法,但是答案并未提及这些概念中的任何一种……无论“可用的库[典范]范式”如何,不能解决眼前的问题,从而回避什么是完全有效的问题。
rinogo


20

这些范例不必相互排斥。如果您看一下python,它支持函数和类,但是同时,所有内容都是一个对象,包括函数。您可以在一个代码中混合并匹配功能/ oop /过程式样式。

我的意思是,在函数式语言中(至少在Haskell中,是我学习的唯一语言),没有任何语句!函数内部只能有一个表达式!!但是,函数是一等公民,您可以将它们作为参数以及一系列其他功能来传递。他们可以用几行代码来完成功能强大的事情。

在像C这样的过程语言中,传递函数的唯一方法是使用函数指针,仅此一项并不能启用许多强大的任务。

在python中,函数是一等公民,但它可以包含任意数量的语句。因此,您可以有一个包含过程代码的函数,但是可以像函数语言一样传递它。

OOP也是如此。像Java这样的语言不允许您在类之外编写过程/函数。传递函数的唯一方法是将其包装在实现该函数的对象中,然后传递该对象。

在Python中,您没有此限制。


我相信您的意思是“这些范例不必相互排斥”。它们的3个正交的,因此理想情况下,您可以在一个程序中使用其中的1个,2个或3个(如果您的语言允许)。
乔·派恩达

是的,我想互斥是一个更好的称呼!谢谢
hasen

14

对于GUI,我会说面向对象的范式非常适合。窗口是对象,文本框是对象,“确定按钮”也是一个。另一方面,诸如字符串处理之类的东西可以用更少的开销来完成,因此可以通过简单的程序范式来更加直接。

我也不认为这不是语言问题。您可以用几乎任何流行的语言编写功能,过程或面向对象的语言,尽管在某些情况下可能需要付出额外的努力。


17
为了使“ Object = GUI小部件”的误解永久存在,我倾向于拒绝投票,但我将避免。OOP在表示抽象概念(例如“ UserAccount”或“ PendingSale”)以及可见的界面元素(例如“ Window”和“ Button”)方面同样有效。
戴夫·谢罗曼

5
我写了一个窗口可以是一个对象。您如何得出每个对象都是从那里开始的窗口的结论?这只是一个例子。当然,OOP也可以用于对抽象实体及其关系进行建模。无论如何,感谢您的支持。无论如何,我没有很多要点:D
panschk,2009年

6
-1。OOP与GUI无关。理想情况下,设计GUI的最佳方法是使用外部文本文件(例如HTML)。虽然像字符串处理之类的事情实际上要用对象来完成。(考虑一下C中的字符串)!
hasen

1
我不知道,也许我只是习惯用对象编程来实现它。但是,如果在不使用对象的情况下更改了TextBox Y的值,您将如何进行一些交互操作,例如更改TextBox X中的值?好的,您可以简单地使用全局变量...
panschk

1
字符串处理是在perl中完成的(比Java,C ++或C#好100倍),但是该语言的字符串功能绝对不是面向对象的。C的字符串处理很糟糕,但是C并不是唯一的过程语言(也不是最好的)。
乔·皮内达

6

为了回答您的问题,我们需要两个要素:

  1. 了解不同体系结构样式/模式的特征。
  2. 了解不同编程范例的特征。

Wikipeida 上的软件体系结构文章中显示了软件体系结构样式/模式的列表。您可以在网络上轻松研究它们。

简而言之,过程式适用于遵循程序的模型,OOP适用于设计,而Functional适用于高级编程。

我认为您应该尝试阅读每个范例的历史,并了解人们为什么创造它,并且您可以轻松地理解它们。

理解了两者之后,您可以将体系结构样式/模式的项目链接到编程范例。


2

我认为它们通常不是“对抗”的,但是您可以将它们组合在一起。我还认为,您提到的词通常只是流行词。很少有人真正知道“面向对象”的含义,即使他们是最猛烈的传福音者。


1

我的一位朋友正在使用NVIDIA CUDA编写图形应用程序。应用程序非常适合OOP范例,并且可以将问题整齐地分解为模块。但是,要使用CUDA,您需要使用C,它不支持继承。因此,您需要变得聪明。

a)您设计了一个可以在一定程度上模拟继承的巧妙系统。可以办到!

i)您可以使用一个钩子系统,该系统希望父P的每个子C都具有对函数F的特定替代。您可以使子注册其替代,该替代将在需要时存储并调用。

ii)您可以使用结构内存对齐功能将孩子投给父母。

这可能很整洁,但是要想出一种面向未来的可靠解决方案并不容易。您将花费大量时间来设计系统,并且不能保证在项目进行到一半时就不会遇到问题。即使不是几乎不可能,实现多重继承也更加困难。

b)您可以使用一致的命名策略,并使用分而治之的方法来创建程序。它没有任何继承,但是因为您的函数很小,易于理解并且格式一致,所以您不需要它。您需要编写的代码量增加了,很难集中精力并且不屈从于简单的解决方案(黑客)。但是,这种忍者编码方式是C编码方式。在低级自由和编写好的代码之间保持平衡。实现此目的的好方法是使用功能语言编写原型。例如,Haskell非常适合原型算法。

我倾向于方法b。我使用方法a编写了一个可能的解决方案,老实说,使用该代码感觉非常不自然。


第一个c ++编译器只不过是生成C代码的预处理器。这样,可以使用C来实现c ++的所有功能-包括多重继承。(在C中模拟c ++异常处理将需要某种平台上的异常支持,但是c ++实现也需要这种支持,因此我认为它不能使基本想法无效)。
克里斯·贝克 Chris Becke)2009年

2
@克里斯·贝克(Chris Becke),您的回答太哲学了。首先,C拥有多种标准(多年来),几乎没有任何标准被C编译器完全采用,更不用说c ++了。说C ++是C的超集是因为它使用C语法,这并没有多大意义,因为您甚至无法为一个C编译器编写代码,而无需花费大量精力就可以在另一个C编译器中进行编译。此外,还有其他语言提供的语言功能(类型系统,OOD支持),如果不使用C设计新语言(这正是为什么有“新语言”的原因),就不可能在C中实现
Sprague

你懂。我再也看不到我的评论与这篇文章有什么关联。:P
克里斯·贝克

Cuda已经支持C ++一段时间了。
Aryeh Leib Taurog
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.