【问题标题】:What's the difference between a procedural program and an object oriented program? [closed]过程程序和面向对象的程序有什么区别? [关闭]
【发布时间】:2009-02-10 01:08:38
【问题描述】:

我对编程还很陌生,但我一直在阅读有关 StackOverflow 的一些关于各种编程方法的有趣讨论。我仍然不是 100% 清楚过程编程和面向对象编程之间的区别。听起来面向对象编程仍然使用过程(方法),但一切的组织方式都不同,因为对象是节目的主角。但在我看来,程序仍然允许你做所有相同的事情。就像在 C 中一样,您可以将所有类似的过程放入一个库中。所以你真的不能说 C 中的库类似于 C++ 中的对象吗?

【问题讨论】:

标签: c++ c oop procedural-programming


【解决方案1】:

在程序化程序中,代码为王,数据为从属。换句话说,您的程序对数据起作用,而且它们通常没有紧密绑定。

在 OO 世界中,对象是最重要的东西。一个对象由数据允许作用于该数据的代码组成,它们之间的联系非常紧密。就是封装的概念,信息的隐藏。

举个例子,假设你有一个数字,你想把它加倍。这样做的程序方法是:

n = n * 2

这里的代码非常明确地将 n 乘以 2 并将结果存储回 n。

这样做的OO方式是向数字对象发送一个“消息”,告诉它自己加倍:

n.double();

这样做的好处叫做多态性。当您决定要能够将“bob”之类的字符串加倍时会发生什么。在程序世界中,您必须提供更多代码来进行加倍,但您还必须以不同的方式调用该代码。

使用 OO,您可以创建一个字符串对象,该对象也可以接收“双重”消息。将字符串加倍的代码属于字符串对象,因此它知道它必须与数字对象不同。如果它决定 "bob" * 2 是 "bobbob",那么代码将类似于:

class number:                    class string:
    int n                           char array s
    procedure double:               procedure double:
        n = n * 2                       s = string_join(s,s)

然后,无论 x 是什么实际类型(数字或字符串),您都可以调用 x.double(),它会知道要运行哪个代码 - 这大大简化了您的代码。您可以在显示器上加倍整数、字符串、矩阵、复数、实数、窗口大小以及各种不同的东西。

你是对的,可以让 C 库看起来有点像对象。经典的例子是stdio.h - 你从不关心FILE* 实际指向的什么,只是它会以某种方式运行的事实。 FILE*fopen()fclose() 和其他函数是代表 C 的 I/O 能力的一类。

【讨论】:

  • 很好的解释。我很惊讶这被选为最佳答案。我认为这真的很成功。
  • 问题:我理解您的示例如何表示多态性的概念,但我不确定它如何表示封装 - 是不是因为双重功能现在包含在一个称为方法?有了方法,我们就有了封装?
  • @WO,封装就是隐藏数据或代码。代码封装是允许多态性的原因,因为代码现在属于对象,而不是让外部代码作用于对象。你告诉对象要做什么,而不是如何去做。它知道该怎么做。封装/多态密切相关。
  • @Willem,我想你的意思是“......很惊讶这没有被选中......”。谢谢,但这就是SO的变幻莫测。提问者决定接受的答案,社区决定最佳答案。你和我都知道我的答案是最好的 :-) 但我们只有两个人(我不能投票)。
  • 这真是一个很好的解释。我认为这将帮助我的很多朋友学习面向对象的入门课程。我会与他们分享。感谢您花时间分享。 :D
【解决方案2】:

您可以在大多数 OO 语言中进行过程式编程,但 OO 的强大之处在于能够继承、封装和抽象该过程逻辑。 我认为你是对的,图书馆应该看起来很像一个类。它应该有自己的作用域,并用有意义的名称封装函数背后的逻辑。

【讨论】:

  • 为了补充您的答案,继承、封装和多态是 OOP 的三大支柱。
【解决方案3】:

您的观察是正确的,面向对象的程序在许多方面都基于过程范式。您在语法上也是正确的,真正发生的只是您调用函数。事实上,您可以使用过程机制(例如,C++ 中的函数指针)来实现面向对象语言的许多特性。因此,您可以进行面向对象的设计,并且仍然用过程语言实现它(例如,就像旧的 C++ 编译器所做的那样)。

面向对象范式的重要性并不在于语言机制,而是在于思考和设计过程。在过程式编程中,思维是关于操作并使用其他操作分解这些操作,将它们分组为模块等。这意味着数据或状态属于次要的重要性。这就像思考数学运算。

另一方面,面向对象的范式表示您需要将状态和操作一起视为一个实体,然后将您的程序设计为交换状态和激活操作的实体之间的交互。

【讨论】:

    【解决方案4】:

    两者之间的区别是微妙但重要的。

    在过程程序中,模块通过读取和写入存储在共享数据结构中的状态进行交互。

    在面向对象的程序中,对象形式的模块通过向其他对象发送消息进行交互。

    【讨论】:

    • 我有一个疑问。 Java 是过程语言吗?
    【解决方案5】:

    恕我直言,面向对象编程是一个存在于比过程编程更高抽象级别的概念。两者并不相互排斥,因为 OO 程序中的各个方法看起来与过程程序中的各个函数几乎相同。这与例如需要完全不同的思维方式的函数式编程形成对比。此外,您可以通过将所有内容设为静态等方式以 OO 语言进行程序化编写。您可以成为人类编译器,并通过使用大量函数指针和结构指针转换在 C 中有效地编写 OO 代码。

    因此,OO 更像是一种设计理念和世界观,而不是具有严格定义的东西。它要求将继承、多态等用作构建代码的主要模式,并提供语法以使这些可表达而无需求助于低级技巧。它要求您将作用于数据集合状态的代码视为数据的属性,而不是自身存在的过程。它不是黑白的。您的代码可以是“更多”或“更少”OO,这取决于您对继承、多态性、类和“作为数据属性的方法”的世界观作为结构化和解释/理解代码的手段的依赖程度。

    【讨论】:

    • 关于 OO 代码与过程代码以及 OO 语言与过程语言之间的区别的好点。上升了。
    【解决方案6】:

    OO 主要是一种思维定势。你可以用 C 编写面向对象(如果你真的想……),你可以完美地用 C++/Java 编写程序代码;我的意思是,即使你在表面上使用类,它仍然可以是程序性的。

    OO 背后的理念是状态抽象。不是根据“数据分组”来“思考”,而是根据“对象”来“思考”,其中对象是“数据分组和操作这些数据的方法”的“接口”。

    这听起来很哲学,因为它是

    这里要说的很多,小SO帖子里也说不完,就放在这里吧。

    更新
    正如Flanagan's answer 中提到的,OO 语言实现了利用这种抽象的结构。

    我的意思是,从技术上讲,您可以在结构、函数和函数指针方面“破解”类和多态性。

    这是OO in C的示例

    【讨论】:

      【解决方案7】:

      [原谅初级风格,来晚了,我累了]

      程序处理数据 - 数据输入,应用一些处理,取出数据

      有时,一些数据元素与其他一些数据元素相关,将它们组合成一个数据结构很方便,然后可以将其作为一个单元进行操作和寻址.

      现在我们的程序可以将一个数据结构作为输入并对其进行修改和/或生成另一个数据结构作为输出

      偶尔我们会注意到一些程序只关心某种数据结构;将这些过程与其数据结构组合在一起很方便,并将其称为对象

      用于创建对象的模板称为;一个对象被称为一个类的实例

      我们可能会注意到一个类与另一个类非常相似,因此我们让一个类继承另一个类而不是复制和粘贴代码:子类继承自超类或“基类”。通过这种方式,子类可以访问超类的所有数据结构和过程,并且可以通过某些方式扩充或覆盖它们

      如果我们礼貌地请求一个对象为我们做某事,而不是直接粗暴地调用它的过程,这称为消息传递,即使没有实际的“消息”被传输。这里的乐趣在于许多不同类型的对象可以理解相同的消息,这导致了多态性的概念。例如,我们可以要求许多不同类型的文档自行打印,它们都会做出适当的响应。

      通过消息传递和继承支持对象(通过或不通过类)的语言称为面向对象。如果没有继承,语言只是基于对象的

      祝你学业顺利!

      【讨论】:

      • 这太棒了!无法想象如果你不累会是什么样子。我正在保存这个。
      • @[Willem Obst]:谢谢 - 如果我有更多时间,它会更短;-)
      • 哇!我希望我的更多老师能像你在这里一样清楚地解释事情。感谢您的贡献!
      • [@Mike Grace]:谢谢你的高度评价。据称我正在写一本书;-) stackoverflow.com/questions/303276/…
      【解决方案8】:

      不同之处在于对象在同一位置具有过程和相关数据 - 过程语言使用“结构”(将相关数据保存在一起的东西)将数据与过程分开。实际上,您在 OO 语言中所做的任何事情都应该在结合了结构和过程的过程语言中成为可能。

      主要区别在于 OO 语言赋予程序员的思维定势。

      【讨论】:

        【解决方案9】:

        过程是描述程序应该做什么的不同方式之间的过程/功能/逻辑(或面向逻辑)区别(比较 c、lisp 和 prolog)的一部分。

        面向对象与另一个想法是正交的,它描述了一种用数据对子程序进行分组的方法。 C++ 和 java 是具有面向对象特性的过程语言; fortran77 是一种没有面向对象特性的过程语言。 Common lisp 支持面向对象;一些较旧的 lisps 没有。普通的 prolog 不支持对象,我无法命名一种支持的面向逻辑的语言(我不进行面向逻辑的编程,当我一些业余时间充裕。我几乎不做函数式编程)。

        然而,正如其他人所指出的那样,正确的面向对象思维会改变您的编程方式,就像从过程式转换到函数式一样。


        顺便说一句——我看到“过程”用于区分非面向对象的过程语言与其面向对象的兄弟,但我认为这是一种糟糕的用法,原因是“非对象”缺乏一个干净的形容词导向”。 YMMV。

        【讨论】:

        • 而不是“逻辑”以避免像“我无法命名逻辑语言......”这样的灾难?是的,我可以看到。
        【解决方案10】:

        在上下文中更容易理解,看看语言之间引入的其他抽象。

        汇编语言与诸如 C 或 Pascal 之类的过程语言之间的主要区别在于引入了“过程”抽象。编写汇编代码的人会创建程序,但它很困难且容易出错,程序语言为您提供了使其更容易的工具。

        过程语言和像 C++ 这样的面向对象语言之间的区别在于“对象”抽象。写“c”的人经常创建概念对象but its difficult and error prone,OO 语言为您提供了工具,让您更轻松。

        来自 Microsoft(或 Erlang)的 Sing# 之类的东西将 Message/Process 抽象添加到语言中。当然,您可以在汇编、C 或 C++ 中进行消息传递和进程创建,但 Sing# 更容易。

        这一切都归结为相同的机器代码,这些抽象纯粹是为了我们的大脑,而不是计算机。

        【讨论】:

          【解决方案11】:

          在程序化程序中,您将一个大问题分解为小问题,并将这些小问题中的每一个抽象为一个过程。这称为过程抽象。

          在面向对象的程序中,您将问题分析为一些对象,以及对象之间的交互。这称为对象抽象。

          【讨论】:

            【解决方案12】:

            区别是

            面向过程的编程 - 重视算法而不是数据。这种编程方式专注于过程,即执行特定任务和共享其数据结构的方法。它遵循自上而下的结构。

            示例:Pascal 和 C

            面向对象的编程 - 重视数据而不是算法。它遵循自下而上的结构。每件事都被视为一个对象。每个对象都有自己的数据结构和过程。它包括数据隐藏、多态性、封装和消息传递等特性。用户在他们的程序中使用它们时,真的不必理会这些对象内部的内容。

            示例:C++ 和 Java

            【讨论】:

              【解决方案13】:

              这是一个简化的答案。

              • 在真正的 OO 语言中,唯一的过程编码是在对象内部完成的。

              • C 没有对象,而 C++ 是一种支持对象的语言。另一方面,Java 一切都是对象(原语除外)。一切都是打字的。

              • 线性进展发生在对象内部,但对象本身只是代码和数据的集合。

              【讨论】:

              • '...对象本身只是代码和数据的集合。'
              • @Richard,感谢您指出我的遗漏。我会改正的。
              【解决方案14】:

              这取决于您如何定义 OOP。就您在对象上调用方法的类 Java OOP 而言,过程编程几乎相同。据我所知,您可以在像 C 这样的过程语言中模拟所有 OOP 原则(封装、抽象、多态性、继承)。证明是 GObject,在某种程度上扩展了 Objective-C,以及许多其他 OOP 语言实现使用C,如 cPython。这是通过使用结构并使用函数对这些结构进行操作来完成的:

              typedef struct {
                  Object *isa;
                  String *name;
                  Date *birthday;
              } Person;
              
              Person *Person_new();
              String *Person_name(Person *self);
              void Person_setName(Person *self, String *newName);
              // ...
              

              界面非常像OOP。它实际上不允许多态性,但它也是可能的。它与 Python 接口非常相似,只是属性与“方法”是分开的:

              class Person(object):
                  def __init__(self):
                      self._name = ""
                      self._age = datetime.datetime.now()
              
                  @property
                  def name(self):
                      return self._name
              
                  @property
                  def age(self):
                      return self._age
              

              我选择 Python 作为示例,因为“self”是显式的,就像在 C 示例中一样。许多 OOP 语言,如 Java,都抽象了这一点。

              还有类似于 Smalltalk 的 OOP,其中消息被发送到对象,而不是调用对象上的方法。乍一看,差异很微妙,但它提供了很多功能和灵活性。这也可以在过程语言中实现,正如 Objective-C 所证明的那样。

              面向对象的编程不一定是一种语言,而是一种范式。 Java、Python、Ruby等面向对象的语言提供语法糖来方便地操作对象,这是“过程语言”和“面向对象语言”的主要区别。

              事实上,一个库,或者更确切地说是对结构进行操作的一组函数,与 C++ 中的对象相同。事实上,C++ 就是这样实现的。

              【讨论】:

                【解决方案15】:

                这里已经提到了很多有趣的点。

                一种思考方式是,在 OO 中,您有“对象”的概念,即具有它们固有的特征和行为的事物。它们通常具有某种公共“接口”,它提供了一种机制来检索有关它们的某些信息,但是对象本身,或者更确切地说它的“类”,限制了哪些信息是公开可用的。对象的内部不会暴露给公众,因为通常不需要知道对象“引擎盖下”的肮脏细节。所以面向对象的程序利用了这个结构,以及其他的东西。

                过程式编程通常不会利用这种将数据和行为耦合到“对象”中的方式。我以前见过它用 C 语言完成,但它并不漂亮,而且涉及到太多的胡闹,无法估计一个人可以用 C++ 做些什么。

                面向对象开发背后的一个想法是,我不应该通过您提供的方式以外的任何方式处理您的数据。如果你只为我提供一个经过深思熟虑的界面,你可以让我诚实。现在,如果您使用的是程序方法,并且您向我发送了一个没有内置保护的结构,那么我可以为所欲为,如果我是愚蠢或邪恶的,我可以更改您可能不希望我做的事情改变。

                当然,如果你很聪明,你可以绕过这个对象,但你必须不妨碍这样做。

                这并不完整,但它是一方面。

                【讨论】:

                  【解决方案16】:

                  C++ 的实现方式让 OO 编程看起来很像过程式编程。你需要稍微转变一下思路。

                  在 C++ 中,对象的方法只是作用于对象的过程。但是在真正的 OO 范式中,您应该将方法视为对象可以接收的潜在消息(即字母)。对象收到一条消息(参数代表消息的负载,即信件的内容)并根据消息改变其状态。

                  【讨论】:

                    【解决方案17】:

                    对于程序和 OO 之间区别的一个相当直观的示例,请尝试学习 Smalltalk。在 Smalltalk 中,一切,我的意思是一切都是对象。没有 if 语句或 while 循环。您可以通过向其他对象发送消息(也就是调用方法)来实现该功能。一开始真的让你头晕目眩,但我想你很快就会理解 OO 应该是什么。

                    【讨论】:

                      猜你喜欢
                      • 2020-05-23
                      • 2016-11-26
                      • 2011-06-29
                      • 2011-05-24
                      • 2016-12-31
                      • 1970-01-01
                      • 1970-01-01
                      • 1970-01-01
                      • 1970-01-01
                      相关资源
                      最近更新 更多