注意:这个问题是我几个月前写的一个博客发帖编辑出来的。在评论 on Programmers.SE中放置了一个指向博客的链接后,有人要求我在这里发布一个问题,以便他们能够回答。这篇文章是我最受欢迎的,因为人们似乎经常在Google上输入“我不懂面向对象的编程”。欢迎在这里回答,或者在Wordpress上发表评论。
什么是面向对象的编程?没有人给我一个满意的答案。我觉得你不会从那些到处说“对象”和“面向对象”的人身上得到一个很好的定义。你也不会从那些只做面向对象编程的人那里得到一个很好的定义。没有一个既懂过程编程,又懂面向对象编程的人给了我一个关于面向对象程序的实际工作的一致的想法。
有人能给我介绍一下面向对象编程的优点吗?
发布于 2010-10-11 14:32:24
将软件看作是存在于计算机中的机器或装配线。一些原材料和部件被送进机器,然后按照一套程序将它们加工成某种最终产品。这些程序是为了按照特定的顺序对某一特定参数(如时间、温度、距离等)对某些原材料或部件执行特定操作。如果要执行的操作的细节不正确,或者机器的传感器没有得到正确的校准,或者某些原材料或部件没有达到预期的质量标准,则可能会改变操作的结果,使产品无法按预期的结果生产。
这样的机器操作非常严格,输入也是可以接受的。机器不会质疑设计者的智能和当前的操作环境。只要它被指示,它就会继续遵循程序。即使原材料或部件的改变会对以后的操作产生巨大的影响,机器仍然会执行它的程序。需要对这一进程进行审查,以确定需要对程序作出哪些修改,以补偿和产生预期的结果。对产品的设计或配置的更改可能还需要对所执行的操作或其订单进行重大更改。虽然负责生产的人很快就认识到尽可能隔离操作以减少它们之间的不良影响的重要性,但许多假设都是假设条件部件在它们经过加工时所处的位置;在某些不同的操作环境中,在最终产品掌握在用户手中之前,可能无法检测到这些假设。
这就是过程编程的样子。
面向对象提供的是一种消除组件条件假设的方法;因此,要对该组件执行的操作以及如何将其集成到最终产品中。换句话说,OOP就像获取处理某个特定组件的过程细节,并将其交给一台较小的机器来完成。负责此过程的大型计算机告诉组件特定的机器它希望完成的操作,但将步骤的细节留给特定于组件的机器处理。
关于面向对象相对于非面向对象软件的优势:
发布于 2010-09-24 17:17:18
从你的博客上看,你似乎既熟悉命令式编程,也熟悉函数式编程,熟悉面向对象编程的基本概念,但你从来没有真正“点击”过它是什么让它有用的。我将试着用这些知识来解释,并希望它对你有帮助。
OOP的核心是使用命令式范式,通过创建“智能”数据结构来更好地管理高度复杂的问题域。在一个(标准的非面向对象的过程)程序中,您有两个基本的东西:变量和知道如何处理它们的代码。代码从用户和其他各种源获取输入,将其存储在变量中,对其进行操作,并生成输出数据,这些输出数据将传递给用户或其他各种位置。
面向对象编程是一种简化程序的方法,方法是采用这种基本模式,并以较小的规模重复它。就像一个程序是一个大的数据集合,它的代码知道如何处理它,每个对象都是一小块数据绑定到知道如何处理它的代码中。
通过将问题域分解成较小的部分,并确保尽可能多的数据直接绑定到知道如何处理它的代码中,您就可以更容易地对整个流程以及构成该流程的子问题进行推理。
通过将数据分组到对象类中,您可以集中处理与该数据相关的代码,从而使相关代码更易于查找和调试。通过封装访问说明符后面的数据,并且只通过方法(或者属性(如果您的语言支持的话)访问它),您将大大减少数据损坏或不变量冲突的可能性。
通过使用继承和多态性,您可以重用已有的类,定制它们以满足您的特定需求,而无需修改原始文件或从头重写所有内容。(这是一个你不该做的事,如果可以避免的话。)请注意,您理解了基本对象,否则您可能会得到杀手袋鼠。
对我来说,这些是面向对象编程的基本原则:复杂性管理、代码集中以及通过创建对象类、继承和多态来改进问题域建模,以及在不牺牲通过使用封装和属性来牺牲能力或控制的情况下增加安全性。我希望这能帮助您理解为什么这么多程序员认为它有用。
编辑:针对Joel在评论中提出的问题,
你能解释一下“面向对象的程序”包含什么(除了你概述的这些花哨的定义之外)与命令式程序有根本不同吗?你是怎么“让球滚开的?”
这里有个小免责声明。我的“面向对象程序”模型基本上是Delphi模型,它与C#/.NET模型非常相似,因为它们是由以前的Delphi团队成员创建的。我在这里说的可能不适用,也不太适用于其他面向对象语言。
面向对象的程序是指所有的逻辑都围绕着对象进行结构的程序.当然,这必须被引导到某个地方。典型的Delphi程序包含初始化代码,它创建一个名为Application
的单例对象。在程序开始时,它调用Application.Initialize
,然后对从一开始要加载到内存中的每个表单调用Application.CreateForm
,然后调用Application.Run,
,它在屏幕上显示主窗体,并启动构成任何交互式计算机程序核心的输入/事件循环。
应用程序和窗体轮询来自操作系统的传入事件,并将它们转换为对象上的方法调用。在.NET中使用事件处理程序或“委托”是非常常见的一件事。一个对象有一个方法,上面写着“做X和Y,但也检查是否分配了这个特定的事件处理程序,如果是的话调用它”。事件处理程序是一个方法指针--一个非常简单的闭包,包含对方法的引用和对对象实例的引用--用于扩展对象的行为。例如,如果我的表单上有一个按钮对象,我通过附加一个OnClick事件处理程序来定制它的行为,这会导致其他一些对象在单击按钮时执行一个方法。
因此,在面向对象的程序中,大多数工作是通过定义具有特定职责的对象并将它们链接在一起来完成的,要么通过方法指针,要么通过一个对象直接调用在另一个对象的公共接口中定义的方法。(现在我们又回到了封装。)这是我在大学参加OOP课程之前没有概念的想法。
发布于 2010-10-11 16:12:45
我认为OOP基本上只是一个名字,你可能一直想做的事情,就像我一样。
早在我还是个初级程序员的时候,即使在Fortran,也有一个指向子程序的指针。能够将指向子例程的指针作为参数传递给另一个子例程是非常有用的。
接下来真正有用的是将指向子例程的指针存储在数据结构的记录中。这样,您可能会说记录“知道”如何对自己执行操作。
我不确定他们是否将其构建到Fortran中,但是在C和它的后代中很容易做到。
因此,在下面,这是一个简单而有用的想法,你可能会被诱惑去做自己的事情,而且用最近的语言做起来更容易,即使有些人把它变成了一股巨大的潮流,充斥着可怕的流行语。
https://softwareengineering.stackexchange.com/questions/7126
复制相似问题