这些编程范式之间有何不同之处?它们是否更适合特定问题,或者有没有使用案例支持其中一种?
建筑样例鉴赏!
他们各有所长,只是不同的方法解决了同样的问题。
在纯粹的过程式风格中,数据往往与对其进行操作的函数高度解耦。
在面向对象的风格中,数据往往伴随着一系列的函数。
以函数式为风格,数据和函数通向有更多的共性(如Lisp和Scheme),同时在实际使用函数方面提供更多的灵活性。而算法的定义也倾向于基于递归和组合,而不是循环和迭代。
当然,语言本身只影响了哪种风格更受欢迎。即使在像Haskell这样的纯函数式语言中,你也可以用过程式的风格进行编写(但这种做法是极度不鼓励的),即使在像C这样的过程式语言中,你也可以以面向对象的风格编程(例如在GTK+和EFL API中)。
要清楚,每种范式的“优点”仅仅在于算法和数据结构的建模。例如,如果你的算法涉及到了列表和树,函数式算法可能是最合适的选择。又比如,如果你的数据高度结构化,那么如果该语言的本机范式是对象,将其组合成对象可能更合理 - 或者,它可以像Haskell或ML等语言的范畴抽象一样轻松地编写成功能性单子范式。
你使用的选择仅仅是因为它对你的项目和语言所支持的抽象更有意义。
我认为现在的可用库、工具、范例和社区完全超越了这个范式。例如,机器学习(或其他什么)可能是终极通用编程语言,但如果你不能获得任何适合你所做工作的好库,你就完了。
举例来说,如果你正在制作一个视频游戏,C++ 中有更多好的代码示例和软件开发工具包(SDKs),所以你最好使用它。对于小型网络应用程序,有一些出色的 Python、PHP 和 Ruby 框架可以让你快速上手。由于编译时检查和企业库和平台,Java 是大型项目的绝佳选择。
过去不同语言的标准库通常很小且容易被复制 - C、C++、汇编语言、ML、LISP 等自带基础内容,但在网络通信、加密、图形、数据文件格式(包括 XML)以及基本数据结构如平衡树和哈希表等标准化方面往往退缩了!
现代编程语言如Python、PHP、Ruby和Java现在都配备了更好的标准库,而且有很多好的第三方库可以轻松使用,这很大程度上要归功于它们采用命名空间来避免库之间的冲突,以及垃圾回收来标准化库的内存管理方案。
这些范例不必是互相排斥的。如果你看看Python,它支持函数和类,但同时,包括函数在内的一切都是对象。你可以在一段代码中混合使用函数式、面向对象、过程式风格。
我的意思是,在函数式语言中(至少在我学习的Haskell中),没有语句!函数只允许一个表达式在它们中间!但是,函数是一等公民,你可以将它们作为参数传递,以及一些其他的能力。他们可以用很少的代码做出强大的事情。
在像C这样的过程化语言中,你唯一能够传递函数的方式是使用函数指针,而这并不能实现很多强大的任务。
在Python中,函数是一等公民,但它可以包含任意数量的语句。因此,您可以拥有包含过程代码的函数,但可以像函数式语言一样传递它。
同样适用于面向对象编程。像Java这样的语言不允许您在类外编写过程/函数。将函数传递给其他方法的唯一方法是将其包装在实现该函数的对象中,然后将该对象传递过去。
在Python中,你没有这个限制。
对于GUI,我认为面向对象的范例非常适合。窗口是一个对象,文本框也是对象,确定按钮也是一个对象。另一方面,像字符串处理这样的东西可以用更简单的过程范例来减少开销,因此更直接。
我认为这不是语言的问题。你可以用几乎任何流行的语言编写功能、过程式或面向对象的代码,虽然在某些语言中可能需要额外的努力。
为了回答你的问题,我们需要两个要素:
在维基百科的《软件架构》文章上显示了一系列软件架构风格/模式清单。您可以轻松地在网络上进行研究。
简而言之,程序化适用于遵循程序的模型,面向对象适用于设计,函数式适用于高级编程。
我认为你应该尝试阅读每种范式的历史,了解人们为什么创建它,这样你可以很容易地理解它们。
了解它们后,您可以将建筑风格/模式的项目链接到编程范例中。
我认为它们通常不是"对立的",而是可以结合起来。我也认为,你提到的这些词往往只是流行语。即使是最热烈的信仰者,也很少有人真正知道"面向对象"的意思。
我的一个朋友正在使用NVIDIA CUDA编写图形应用程序。该应用程序非常适合OOP范 paradigm,而且问题可以很好地分解成模块。但是,要使用CUDA,您需要使用不支持继承的C。因此,您需要聪明才能解决问题。
你设计出一个聪明的系统,可以在一定程度上模拟继承。这是可以实现的!
你可以使用钩子系统,该系统期望父级P的每个子级C都有特定的函数F的覆盖。您可以使子级注册其覆盖,这些覆盖将在需要时存储并调用。
ii)您可以使用结构体内存对齐的特性将子类强制转化为父类。
这很棒,但要想出具有未来保障、可靠的解决方案并不容易。您将花费大量的时间设计系统,没有保证您不会在项目过程中遇到问题。如果实现多重继承,或几乎是不可能的,甚至更加困难。
你可以使用一致的命名策略和采用“分而治之”的方法创建程序。它不需要继承,但由于你的函数小且易于理解,并且格式一致,所以不需要。需要编写的代码量会增加,很难保持专注且不陷入简单解决方案(黑客)。然而,这种忍者式编码是C式编码的方式。保持在低级自由和编写良好代码之间保持平衡是实现这一目标的好方法。使用函数式语言编写原型是实现这一目标的好方法。例如,Haskell非常适合原型算法。
我倾向于方法b。我用方法a写了一个可能的解决方案,老实说,使用那个代码感觉非常不自然。