【问题标题】:Defining OOP for a new programmer [closed]为新程序员定义 OOP [关闭]
【发布时间】:2010-10-10 11:34:30
【问题描述】:

在向没有编程背景的人教授第一语言时,尽管我更喜欢 OOP,但我很难定义 OOP,我如何向编程经验很少(或零)的人定义 OOP?

【问题讨论】:

标签: oop


【解决方案1】:

您可以尝试以下方法,我在前一段时间在论坛上发布的帖子中对此进行了稍微修改:

OOP 最基本的词汇集是类、方法和参数。

类是一组协同工作以完成任务的函数。一个类的实例被认为是一个对象。

方法只是指封装在类中的函数。

参数是一个变量,它被传递给一个函数,指示它如何行动或提供信息以进行处理。

如果您进行一些挖掘,您会发现大量有关设计模式的信息。其中一些可能很有用,尽管我一开始会小心不要过多地进入它们,因为它们可能会让人不知所措。在尝试让自己进入 OOP 思维模式时,您可能会记住两个有用(并且有些过度使用)的首字母缩略词:DRY 和 KISS。

DRY 代表 Don't Repeat Yourself,意思就是这样。如果您编写了一些代码,则不必再重复该特定代码。实际上,这意味着从一开始就进行更抽象的思考和更好的计划。我马上举个例子。

KISS 代表 Keep It Simple, Stupid,意思是您应该尝试编写以尽可能简单的方式实现其目标的代码。更简单意味着更少的错误可能性和更容易的维护。在 OOP 的上下文中,这通常意味着确保每个方法或函数只有一个任务。如果你发现一个方法做不止一件事,这通常意味着它可以被重构为几个更小的方法,每个方法专门用于特定的任务。

现在举一个简单的例子(有人可能会想出一个更好的例子,但现在跟我一起去吧):

假设您需要对两种不同的表单进行编程,一种用于处理汽车信息,另一种用于处理卡车信息。

对于汽车,我们需要记录以下信息:

  • 颜色
  • 发动机尺寸
  • 传输类型
  • 门数

对于卡车,我们需要:

  • 颜色
  • 发动机尺寸
  • 传输类型
  • 驾驶室尺寸
  • 牵引能力

在过程式编程中,您会先编写代码来处理汽车表单,然后再编写代码来处理卡车表单。

使用面向对象的编程,您将编写一个名为vehicle 的基类,它会记录我们需要的卡车和汽车的共同特征。在这种情况下,车辆类将记录:

  • 颜色
  • 发动机尺寸
  • 传输类型

我们会将这些特征中的每一个都制成一个单独的方法。例如,color 方法可以将车辆的颜色作为参数并对其进行处理,例如将其存储在数据库中。

接下来,我们将创建另外两个类:卡车和汽车,这两个类都将继承车辆类的所有方法,并使用它们独有的方法对其进行扩展。

汽车类将有一个名为 numberOfDoors 的方法,而卡车类将有一个方法 cabSize 和 towingCapacity。

好的,让我们假设我们有一个适用于过程和 OO 编程的工作示例。现在,让我们来看看几个场景。

场景一:假设我们突然需要添加一个总线表单,它记录了以下信息:

  • 颜色
  • 发动机尺寸
  • 传输类型
  • 乘客人数

程序:我们需要重新创建整个表单,重复颜色、引擎大小和传输类型的代码。

OOP:我们只是用一个公共汽车类扩展车辆类并添加方法 numberOfPassengers。

场景 2:我们的客户没有像以前那样将颜色存储在数据库中,出于某种奇怪的原因,我们的客户希望通过电子邮件将颜色发送给他。

程序:我们更改了三种不同的形式:汽车、卡车和公共汽车,以通过电子邮件将颜色发送给客户,而不是将其存储在数据库中。

OOP:我们更改了车辆类中的颜色方法,因为汽车、卡车和公共汽车类都扩展(或继承自,换句话说)车辆类,它们是自动更新。

场景 3:我们希望从普通汽车转向特定品牌,例如:Nissan 和 Mazda。

程序:我们为每个品牌创建一个新表单,重复通用汽车信息的所有代码并添加特定于每个品牌的代码。

OOP:我们使用 nissan 类和 mazda 类扩展汽车类,并为该汽车品牌的每组唯一信息添加方法。

场景4:我们在表单的传输类型区域发现了一个bug,需要修复它。

程序:我们打开并更新每个表单。

OOP:我们在车辆类中修复了 transmissionType 方法,并且该更改在继承自它的每个类中都持续存在。

从上述场景中可以看出,采用 OOP 风格比过程式编程具有显着优势,尤其是随着规模的扩大。考虑一下如果我们还必须为船、摩托车、飞机、卡丁车、ATV、雪地摩托等添加表单,我们将从 OOP 获得的重复代码、灵活性和维护方面的节省。

通过使用单元测试来测试结果,对象和方法也比过程式编程更容易测试。

这是否意味着您永远不应该使用过程式编程?不必要。如果你正在做一个模型或概念验证应用程序,你可能没有时间让所有东西都面向对象,所以我认为对原型使用过程编程可能会更好,但最好以OO方式制作生产产品。

【讨论】:

  • 在我看来,这对于初学者来说有点过于正式了......但写得很好;-)
  • 重读这个问题,我想你可能是对的。如果他们至少有一点编程经验,这可能会有所帮助。这在论坛上回答的问题是关于程序和 OOP 样式的,所以它可能不完全适合......
  • 不过,在我使用它之前,我可以满足理解这一点所需的先决条件。
  • DRY 和 KISS 与面向对象编程没有任何关联。它们是通用的编程概念。
  • 这是 2 个整页打印的 BTW ;)
【解决方案2】:

我以“弹跳球”为例。想象一下,你有一个盒子,里面有一个弹跳球。

您可以通过两种方式对其进行编程:

一种方法是运行一个循环,跟踪球的当前位置,计算下一个位置,检查碰撞,从当前位置擦除,在新位置绘制它。重复。

另一种方法是让球跟踪自己的位置和方向,并教它计算下一个位置以及如何移动到那里以及如何处理碰撞。然后,运行循环并告诉小球不断更新自己。

现在假设您有 100 个球。然后是重球、轻球和爆炸球。这些是具有附加特性的基本球。你还会用方法一吗?

【讨论】:

  • 这是一个很好的描述。干得好。
【解决方案3】:

好吧,您应该使用示例。大多数人理解的一个例子是参考视频游戏。因此,您有怪物对象,而怪物具有某些属性,例如颜色、大小、形状、手臂数量等。然后一些怪物有不同的“能力”,比如喷火,射击枪等等。这些都是愚蠢的例子,但很容易理解。我认为向新手解释“正方形”、“圆形”等比所有这些业务更容易。

【讨论】:

  • 我有点不同意,因为人们普遍认为“对象”的意思是“您可以在屏幕上看到的东西”(通常是按钮、文本框等)并使用视频游戏怪物(它们是在屏幕上可见)将提供给它。
  • 我同意这种讨论对年轻人来说变得非常有趣。我打算在以后的课程中使用它。
  • 嗯,我已经看到它使用了很多,并没有真正遇到将对象与可见事物混淆的问题。我认为利大于弊。转到概念/抽象/不可见对象并不是一个飞跃。我认为它更容易理解,因为它曾经在课堂上取得成功。
【解决方案4】:

不要浪费时间“定义”OOP。

只需对所有示例使用 OOP 语言即可。

对象是微不足道的。现实世界充满了物体。

不要“定义”对象。只是显示编程示例,'对象性'会很明显。

没有编程背景的人不会对过程式编程抱有愚蠢的期望。

学过COBOL或Basic的人会有问题。


这部分取决于语言。某些语言使 OOP 变得困难。

例如,在 C++ 中,“类”只是定义性的。它在运行时不作为离散对象存在。

在 Java 和 C++ 中,有些东西是对象,但一些“原始”类型不是对象。

某些语言使 OOP 更容易。

Python 和 Smalltalk 一切都是对象。没有原始类型可以搅浑水。当你用 Python 这样的语言学习 OO 时,对象性是清晰而明显的,因为它无处不在。就像现实世界一样,物体无处不在。

【讨论】:

  • 如果对象是微不足道的;那么为什么这么多开发人员在选择好对象方面如此糟糕呢?在许多情况下,它们甚至根本不是对象。
  • @Dunk:因为许多程序员首先学习了过程编程:VB 或 C 之类的。
  • 我不确定对象是否显而易见,但我认为您的想法是正确的。不要定义它,做它。以应该编写代码的方式呈现它。然后稍后再回来解释你一直在做什么(以及其他可用的范例)。
  • 2 小时后,我写了同样的东西,但很啰嗦。请参阅下方投票数为 0 及以下的答案。
【解决方案5】:

我会将其解释为对现实世界信息进行建模的一种方式。有一个常见的类比是使用汽车和车辆来显示类型层次结构。如果你解释正确的话,我认为这对大多数人来说都很简单。

也许您应该从解释原始类型开始,然后讨论结构等复合类型,然后展示如何使用继承将这些类型关联为类。

编辑:经过考虑,动物的例子要好得多。请参阅Explaining OOP without Mentioning Classesthis SO thread 了解相同的主题。

【讨论】:

    【解决方案6】:

    一个运动队。任何时候的场上/球场上的球员都可以根据他们所扮演的位置来指定。但是,整个团队可能有多个成员可以担任给定位置。

    每个位置就像OO中的一个类;它指定了一组职责。团队成员是这些类的实例。

    剧本中的剧本是模式。每一个都指定了如何通过位置(类)的(实例)交互来达到特定的结果。

    【讨论】:

      【解决方案7】:

      假设您要描述一个具有相同属性但可能具有不同名称、颜色或其他外观差异的事物系列。

      例如,您想描述一个家庭在车库中拥有的车辆。您感兴趣的每辆车都有一些属性:

      1. 每辆车的型号和年份是什么?
      2. 一辆车有多少个轮子?
      3. 驾驶特定车辆的人员是谁?

      在这种情况下,您可能有一组两辆汽车,因此以下情况为真:

      Vehicle A's Model is a Toyota.
      Vehicle A's Year is 2001.
      Vehicle A has four Wheels
      Vehicle A is driven by Mom, Dad, and Junior
      
      Vehicle B is a Moto Guzzi
      Vehicle B was made in 2004
      Vehicle B has two wheels
      Vehicle B is driven by Dad
      

      在各种语言中,您可能会以以下等效方式非常粗略地引用这两个示例:

      A = new Vehicle();
      A.model = "Toyota";
      A.year = 2002;
      A.wheelCount = 4;
      A.drivers = [ "Mom", "Dad", "Junior" ];
      
      B = new Vehicle();
      B.model = "Moto Guzzi";
      B.year = 2004;
      B.wheelCount = 2;
      B.drivers = [ "Dad" ];
      

      在 OOP 中,您正在封装这些车辆的属性,以便您可以通过它们的特性来描述它们。你的工作是编写代码来获取和设置这些特性的值(以及用这些特性做其他有趣的事情)。

      此外,您可以“子类化”,这是一种在不同上下文中重用对象的方法。例如,您可以使用更具体的 Vehicle 对象类型,例如 Car 和 Motorcycle,它们从 Vehicle 的描述中继承其特征:

      A = new Car();
      B = new Motorcycle();
      

      Car 和 Motorcycle 对象是对车辆的更具体的描述。这两个子类可以有自己的特殊属性。汽车可能有儿童锁,而摩托车通常不需要这样的东西。

      您可以说只有 Car 具有 Lock 属性,而不是设置 Vehicle 的 Childproof Lock 属性。这使您的车辆描述更清晰,更易于编写和维护。

      【讨论】:

        【解决方案8】:

        据我所知,面向对象编程最初是指将程序的所有概念组织成对象,然后将所有逻辑流定义为这些对象之间的消息。我觉得要想明白本意,就得学习Smalltalk。

        【讨论】:

        • 很好的答案。一个小建议:IMO,Self 实际上在教授 OO 编程方面甚至比 Smalltalk 更好,因为 Self 真的只有对象和消息——没有变量、没有常量、没有类。
        【解决方案9】:

        这是一个简单的定义。

        Gun gun = new Gun(new Bullet);
        gun.Aim = Appendage.Foot;
        gun.PullTrigger();
        

        ;)

        【讨论】:

          【解决方案10】:

          外行面向对象编程:

          1. 程序中的所有内容都是事物(对象)。这东西具有解释它的属性(大小、形状、颜色等)
          2. 程序员要求事物做事/回答问题:让你的尺寸变大 (setSize) 或你的尺寸是多少 (getSize)

          事物仅在您要求(调用方法)时才负责调整其属性。您不能直接检查或更改 事物的 属性。您只能检查或更改 事物 让您看到的属性。因此,thing 可以确保正确查看和更改属性。

          这可以防止程序员告诉事物它的size红色。如果您直接告诉事物将其尺寸设为红色,则它应该拒绝(红色不是有效尺寸)。此外,它还允许事物管理更改其属性的副作用。

          假设 事物的 originalSizebig。如果只是把thing's size改成small要记得告诉事物,它不再是它的 originalSize。如果我 要求 thing 将其 size 更改为 small 它会将其尺寸更改为 small 并将 originalSize 更改为错误的。现在,当我问它是否是它的 originalSize 时,它​​会回答否。

          本质上,这允许您将数据和函数打包在一起,从而使事情更加模块化/分区。这使您可以更好地组织代码并更轻松地重用代码。 OOP 并不是什么特别的东西,它只是一种更好地组织代码的方法。在初学者级别并不重要,但对大型项目至关重要。在 Object 的函数中,事情通常变得更加程序化,就像初学者习惯的那样。

          【讨论】:

            【解决方案11】:

            object 只是一个具有一堆命名属性的事物。这些属性的值定义了一个对象的状态。对象之间的交互是通过消息传递完成的。一条消息由一个名称和一组参数组成。当对象接收到消息时,该消息由对象处理。处理消息可能会导致对象的状态发生变化,并将消息发送到其他对象。

            【讨论】:

            • 切入正题
            【解决方案12】:

            对 OOP 的任何解释都强烈依赖于解释者对概念的解释。我对这个概念的解释是这样的。

            现实世界在很大程度上被理解为一组演员。每个参与者都有一组属性和行为。在大多数情况下,参与者的属性通过其行为以及与其他参与者的交互来表示。

            计算机程序通常是对某些现实世界过程的模拟,因此它通常可以帮助程序员基于参与者-行为-属性模型构建程序。也就是说,整个程序的每个元素都可以分成代表单个参与者的更小的程序。

            当然,您只能做到这一点。并非我们想要建模的所有东西都是单个演员。例如,货币是守恒的,但在许多方面可以无限​​细分。

            此外,对现实世界进行建模的其他方法可能会以更大的抽象为代价提供更严格的正确性保证,例如源自集合论的关系模型。 OOP 没有这样的数学基础。

            【讨论】:

              【解决方案13】:

              它就像倒着拼出来的馅饼一样简单。 oo 的 3 个基本原则是:

              封装 遗产 多态性

              向新手展示大多数 oo 编程书籍中的标准绘制形状示例的代码。还使用大量带有全局数据的开关向他们展示非 oo 代码。

              他们应该根据两组代码之间的组织差异对 oo 有所了解。

              【讨论】:

                【解决方案14】:

                这很奇怪。 您问的是向对编程一无所知的人教授 OOP,而每个人都在回答“如何教授 OOP?”

                答案是,你没有。您如何向从未编程过的人教授函数式编程?你没有。你有函数,代码被塞进它们,它们被重用,等等。在 Java 中,你的所有代码都必须在一个类中。什么是班级?首先,它是放置代码的地方。程序从 Main 方法开始。稍后,您可以实例化它,并且每个类都有自己的方法和属性。然后你谈论静态方法和变量。然后稍后您会谈到多态性和继承。有时他们开始设计自己的 API 并使用 servlet 和持久类或任何最新实现的东西(snervlets?IHibernate?)

                但是,如果您以前从未见过编程,则没有必要坐下来进行 OOP 大讨论。只有当您从非 OOP 编程中拯救某人时才有必要这样做。只教编程。面向对象编程?还有其他种类吗?是的,但我们今天不教这个,所以不用担心。

                [打个比方:你去上武术课,他们通常不会花很多时间解释。首先你伸展,他们让你锻炼,然后他们教你一些技巧。如果您有兴趣弄清楚您正在学习哪种武术,请前往图书馆。]

                【讨论】:

                • 你把问题想太多了,当然要先讲基础。
                【解决方案15】:

                无论您向谁解释这一点,都需要先了解基本编程是什么,然后才能了解 OOP 的含义,因为它是编程语言的一个分支。如果他不了解 OOP 的对应物,他将永远无法理解是什么让 OOP 如此特别。所以你的问题有两个部分;如何解释什么是编程语言以及 OOP 与其他编程语言的区别。

                向他解释一般编程是什么的最简单方法是将其与数学运算进行比较。您可以通过将编程定义为接受输入并产生输出的许多数学表达式来解释它。您希望详细说明的程度取决于您。

                通过这个解释,我们已经完成了基础工作,让他了解 OOP 的含义。现在我们可以将对象定义为一组数学函数和数据。因此,我们不是将逻辑视为全局代码块,而是将这些代码块收集在对象中以收集相关的代码片段并获得隔离它们的方法。从这一点开始,您可以解释对象抽象带来的更多优势(例如多态性、松散耦合)。

                【讨论】:

                • 更准确的定义是函数和数据的集合。每个函数都接受对象及其其他参数。否则,由于潜在的状态变化,它不是一个函数。让我想起了 Python。不幸的是,这对于说明如何使用对象并不是那么有用。
                猜你喜欢
                • 2012-03-04
                • 2012-03-15
                • 2013-05-20
                • 2010-09-28
                • 1970-01-01
                • 1970-01-01
                • 2012-09-20
                • 1970-01-01
                • 1970-01-01
                相关资源
                最近更新 更多