当我开始使用面向对象的语言(Java)时,我几乎刚刚“很酷”开始编码。直到最近阅读了很多有关OOP的问题,我才真正考虑过它。我得到的一般印象是人们为之奋斗。由于我没有想到这一点,而且我不会说我有任何天才,所以我认为我一定错过了或误解了它。

为什么OOP难以理解? 很难理解吗?

有帮助吗?

解决方案

我个人发现OOP的机制相当容易掌握。对我来说,困难的部分是它的“为什么”。当我第一次接触到它时,它似乎是一个解决问题的解决方案。这是我认为大多数人觉得很难的一些原因:

  1. 恕我直言,从一开始就教oo是一个可怕的主意。程序编码不是“坏习惯”,也是某些工作的正确工具。无论如何,OO计划中的个别方法往往看起来很漂亮。此外,在学习程序编程足以使其限制变得可见之前,OO似乎对学生来说并不是很有用。

  2. 在真正掌握OO之前,您需要了解数据结构的基础知识和较晚的绑定/高阶功能。如果您甚至不了解构造数据的概念,而不仅仅是使用primitives并传递高阶函数/指示功能。

  3. 设计模式应被教导为OO的基础,而不是更先进的东西。设计模式可帮助您通过树木看到森林,并为OO简化实际问题的何处提供相对具体的例子,并且您最终想学习它们。此外,一旦您真正获得了OO,大多数设计模式在事后就会变得显而易见。

其他提示

我认为尚未提及一些因素。

首先,至少在“纯OOP”(例如,Smalltalk)中 一切 是一个对象,您必须将思想扭曲成一种相当不自然的配置,才能将数字(仅一个示例)视为智能对象,而不仅仅是一个值 - 因为在现实中, 21 (例如)真的 只是一个价值。一方面,当您被告知OOP的一个很大的优势是更紧密地建模现实时,这变得尤其有问题,但是您首先要采取看起来像LSD启发的可怕的观点,即使是最基本和明显的部分现实。

其次,OOP中的继承也不会紧密地遵循大多数人的心理模型。对于大多数人来说,最具体地对事情进行分类 不是 拥有接近创建有效类层次结构所需的绝对规则。特别是创建一个 class D 从另一个继承 class B 意味着对象的对象 class D 绝对分享 全部 的特征 class B. class D 可以添加自己的新特征,但 全部 的特征 class B 必须保持完整。

相比之下,当人们在心理上对事情进行分类时,他们通常会遵循一个更宽松的模型。例如,如果一个人对构成一类对象的哪些规则制定一些规则,那么只要遵循足够的其他规则,几乎任何一个规则都可以违反。即使是几个不能真正破坏的规则,几乎总是可以“伸展”一点。

例如,将“汽车”视为课程。很容易看到 广阔的 大多数人认为“汽车”的大多数都有四个轮子。但是,大多数人已经看到(至少是一张只有三个轮子的汽车的照片)。我们的一些年龄段的人还记得80年代初(左右)有六个轮子的一两辆赛车 - 等等。这给我们带来了三个选择:

  1. 不要对汽车拥有多少车轮的任何意见 - 但这往往会导致隐含的假设,即始终是4,而代码可能会破坏另一个数字。
  2. 断言所有汽车都有四个轮子,即使我们知道它们确实是,也只将其他汽车归类为“不汽车”。
  3. 设计课程以允许轮子数量变化,以防万一,即使很可能将这种功能不需要,使用或正确测试。

关于OOP的教学通常集中在建立巨大的分类法上 - 例如,地球上所有已知生活的巨大层次结构,或者是该秩序上的东西。这引发了两个问题:首先,它倾向于导致许多人专注于与手头问题完全无关的大量信息。在某一时刻,我看到了关于如何建模狗的漫长讨论,例如(例如)“微型贵宾犬”应该从“全尺寸的贵宾犬”继承,反之亦然,或者是否应该有抽象的基础” “班级,“全尺寸贵宾犬”和“微型贵宾犬”都从中继承。他们似乎都忽略了该应用程序应该处理狗的许可证,为了手头目的,完全足以将一个名为“ breed”(或该订单上的东西)的字段,没有完全对品种之间的关系进行建模。

其次,几乎重要的是,它导致着眼于项目的特征,而不是专注于对手头任务很重要的特征。它导致对事物进行建模,在哪里(大多数时候)真正需要的是建立最简单的模型,以满足我们的需求,并使用抽象来适合 必要的 子类适合我们建立的抽象。

最后,我再说一次:我们 慢慢地 遵循这些年来数据库采取的相同路径。早期数据库遵循分层模型。除了专门关注数据之外,这是单个继承。在短时间内,一些数据库遵循网络模型 - 与多个继承基本相同(从这个角度看,多个接口与多个基类别不足以引起注意或关心)。

然而,很久以前,数据库在关系模型上很大程度上收敛(尽管它们不是SQL,但在这种抽象级别上,当前的“ NOSQL”数据库也是相关的)。关系模型的优势众所周知,我不会在这里重复这些重复。我只注意到,我们在编程中拥有的关系模型的最接近的类似物是通用编程(对不起,但是尽管名称为Java Generics,但一个例子,尽管它们是真正的限定,尽管它们是迈出的一小步正确的方向)。

OOP需要抽象思考的能力;很少有人,甚至是专业程序员的礼物/诅咒。

我认为您可以通过这种方式总结基本困难:

// The way most people think.
Operation - object - parameters
// Example:
Turn the car left.

// The way OOP works conceptually
Object - operation - parameters
// Example:
Car.Turn(270);

当然,人们可以习惯于“左”为270的映射,是的,说“汽车”而不是“转车”并不是一个巨大的飞跃。但是,要很好地处理这些对象并创建它们,您必须颠倒通常的思维方式。

我们没有操纵对象,而是告诉对象实际做事。这可能不再困难了,但是告诉一个窗口打开的声音听起来很奇怪。人们不采取这种思维方式必须一遍又一遍地挣扎,直到最终以某种方式变得自然。

对于大多数人来说,任何范式都需要一定的“越过边缘”才能掌握。从定义上讲,这是一种新的思维方式,因此需要一定数量的放开旧观念,并需要一定程度的完全掌握新概念为何有用。

我认为很多问题是,用于教授计算机编程的方法总体上很差。 OOP现在很普遍,以至于它并不那么明显,但是您仍然经常在功能编程中看到它:

  • 重要的概念被隐藏在奇怪的名称后面(fp:什么是一个单子?

  • 奇怪的概念是在隐喻中而不是用它们实际做的事情或为什么使用它们的原因来解释的,或者为什么有人想过使用它们(fp:a monad是太空服,它包含了一些代码。物体就像鸭子一样,它可以发出噪音,走路并从动物中继承)

  • 好东西因人而异,因此尚不清楚任何学生的转折点,而且老师通常都不记得。 (fp:哦,单调让您将某些内容隐藏在类型本身中并继续进行,而无需显式写出每次都发生的事情。哦:哦,对象让您保留具有该数据的数据的功能。)

最糟糕的是,正如问题所表明的那样,有些人会立即立即了解为什么概念是好的,而有些人则不会。这实际上取决于临界点是什么。对我来说,抓住对象存储数据和方法的方法是关键,此后其他所有内容都适合自然扩展。然后,我后来跳了跳跃,就像意识到来自对象的方法调用与用该对象作为第一个参数进行静态调用非常相似。

稍后,小小的帮助完善理解,但最初是一个使一个人从“ OOP”中带来的,为什么人们这样做?”要“ OOP是最好的,人们为什么还要做其他事情?”

因为OOP的基本解释与该领域的使用方式无关。大多数用于教学的程序都试图使用物理模型,例如“将汽车视为对象,车轮是对象,门以及传输……”,但在某些模拟编程的一些晦涩的案例之外,物体经常用于表示非物理概念或引入间接。效果是它使人们以错误的方式直观地理解它。

从设计模式的教学是描述OOP的一种更好的方法,因为它表明程序员如何通过对象有效地攻击某些实际建模问题,而不是在摘要中描述它。

我在大多数情况下不同意Dsimcha的回答:

  1. 从一开始就教OO并不是一个真正的坏主意,也不是教程序语言。重要的是,我们教人们编写清晰,简洁,凝聚力的代码,无论OO或程序如何。

  2. 良好的OO程序中的个别方法根本不会是程序性的。随着OO语言的发展,这变得越来越正确(阅读C#,因为除了C ++以外,这是我所知道的唯一其他OO语言)及其语法越来越复杂(lambdas,linq to objects等)。程序语言中的OO方法和程序之间的唯一相似性是每种方法的线性性质,我怀疑这会很快改变。

  3. 您也不能在不了解数据结构的情况下掌握程序语言。指针概念对于程序语言与OO语言一样重要。例如,通过参考来传递参数,在程序语言中非常普遍,需要您理解指针与学习任何OO语言所需的同样多。

  4. 我认为根本不应该在OO编程中教授设计模式,因为它们根本不是OO编程的基础。绝对可以成为一个好的OO程序员,而无需了解设计模式。实际上,一个人甚至可以使用众所周知的设计模式,甚至不知道它们被记录在适当的名称中,并且书写了有关它们的书籍。应该从根本上讲授的是设计原则,例如单个责任,开放关闭和界面隔离。不幸的是,如今,许多认为自己的程序员的人要么不熟悉这个基本概念,要么只是选择忽略它,这就是为什么我们在那里拥有如此多的垃圾OO代码。只有在对这些原则和其他原则进行彻底了解之后,才能引入设计模式。

为了回答原始海报的问题,是的,oo是一个比程序编程更难理解的概念。这是因为我们没有根据现实生活对象的属性和方法来思考。例如,人的大脑不容易将“ Turnon”视为电视的一种方法,而是将其视为人类打开电视的函数。同样,多态性是人类大脑的外国概念,通常只用一个“脸”看到每个现实生活对象。对我们的大脑来说,再次继承并不自然。仅仅因为我是开发人员并不意味着我的儿子是一个。一般而言,在程序语言更为自然的同时,需要对人脑进行培训才能学习OO。

我认为许多程序员在前期设计和计划首先都很难。即使有人为您完成所有设计,仍然有可能摆脱OOP原则。如果我拿一堆意大利面条代码并将其倒入一堂课,那真的吗?不了解OOP的人仍然可以在Java编程。另外,不要混淆难以理解的理解,不愿意遵循某种方法或不同意它。

你应该阅读 对象永远不会?好吧,几乎永远不会。 (要求ACM会员资格)Mordechai Ben-Ari建议OOP是如此困难,因为它不是一个自然而然地模拟任何东西的范式。 (尽管我对这篇文章有所保留,因为目前尚不清楚他认为该计划需要满足哪些标准,以说它是在OOP范式上写的,而不是使用OO语言的程序范式。

面向对象的编程本身并不难。

困难的部分是做得很好。在哪里可以将剪切放置在代码之间,以便您可以轻松地将事物移至公共基本对象,然后将其扩展到以后扩展?如何使您的代码可由他人使用(扩展类,代理中包装,覆盖方法),而无需跳过箍。

那是困难的部分,如果做对的话,可能会非常优雅,如果做得不好,可以是 非常 笨拙。我的个人经验是,在所有希望自己做的事情的情况下,都需要很多练习才能做到足够好 这个 时间。

我只是看了理查德·费曼(Richard Feynman)的视频,讨论人们在思考时实际上可能在脑海中发生完全不同的方法 - 我的意思是完全不同。

当我进行高级设计时,我碰巧可视化对象,我可以看到它们,查看它们的界面,并查看需要穿越的路径信息。

我也很难记住细节,发现OO是一个很好的组织援助 - 比通过松散组织的子例程清单扫描更容易找到功能。

对我来说,oo是一个很大的好处,但是如果您不以相同的方式可视化或不进行高级架构,那可能毫无意义且令人讨厌。

我在被介绍给OO之前就完成了GW-BASIC和TURBO PASCAL编程,因此最初 做过 做我的头。

不知道这是否是他人发生的事情,但对我来说就是这样:我关于编程的思考过程纯粹是程序性的。如:“这样发生的事情,然后发生这种情况下的下一步”等。我从来没有考虑过变量和数据是程序流程中的短暂参与者。编程是“行动流”。

我想什么并不容易掌握(现在看起来像我一样愚蠢),这是数据/变量实际上 真的很重要, ,从某种意义上说,不仅仅是在计划“流”中转瞬即逝的演员。或换句话说:我一直试图通过什么来理解它 发生, ,而不是通过什么 , ,这是抓住它的真正关键。

我认为这并不难理解,但可能是许多程序员查询是来自程序语言的新概念的新概念。

根据我所看到/阅读的人(至少在论坛中),从OOP那里寻求“结果”。如果您是一个程序程序员,他不返回并修改扩展其代码,则可能很难理解好处。

另外,那里还有很多不良的OOP,如果人们正在阅读/看到那件事,那么很容易看出为什么他们可能会发现这很困难。

IMO您需要等到它“点击”或由具有真实知识的人教给它,我认为您不会急于。

我认为OOP对许多人来说很难的原因是因为工具并不能真正促进它。

当今的计算机语言是计算机中发生的事情的抽象。

OOP是表示抽象的一种抽象方法。

因此,我们正在使用抽象来构建抽象的抽象。除此之外,我们抽象的是非常复杂的身体/社交互动,也就不足为奇了。

实际上,我有一个名为“在面向对象的编程中挣扎的博客”,这是我在学习中的一些挣扎中诞生的。我认为我很难理解,因为我花了很多时间使用程序编程,而且我很难解决一个想法,即可以通过属性和行为的集合来代表一个物体(我习惯了仅仅是变量和方法的集合)。

另外,还有很多概念使语言对象引向以遗传,界面,多态性,组成等。方式,尽管使用程序编程,但这只是理解诸如变量的内存分配之类的问题,以及对其他方法的切入点调用。

动机。当您看不到为什么,以及您看不到自己所做的事情并弄清楚自己是否做对时,很难学到一些东西。

需要的是小型项目,这些项目使用OO来做有用的事情。我建议您查看一本关于设计模式的书,并提出一个显然有用的书,并且与OO配合得很好。 (我一次尝试过一次策略。像轻量级或单身人士之类的东西是不好的选择,因为它们通常是使用对象,而不是使用对象来完成某件事。)

我认为这取决于年龄(年龄是经验的代理),更重要的是兴趣。如果您“年轻”(即绿色),而您从未想过任何其他方式,那似乎很简单。另一方面,如果您认为这是您见过的最酷的事情 - 在我28岁时就发生在我身上,那么很容易被抓住。

另一方面,如果您认为,就像我的许多Java学生一样,“我们为什么要学习这件事,这只是一种时尚”,这实际上是不可能的。大多数技术都是如此。

无论您选择哪个范式(OOP,功能等),要编写计算机程序,您都需要知道程序将执行哪些步骤。

定义过程的自然方法是写下步骤,对于较大的任务,您将任务分解为较小的步骤。这是程序的方式,这就是计算机的工作方式,这就是您逐步浏览清单的方式。

OOP是另一种思维方式。您没有想到需要逐步完成的任务清单,而是考虑对象,它们的能力和关系。因此,您将编写许多对象,小方法,并且您的程序将神奇地工作。为了实现这一目标,您需要扭曲您的思想...

这就是为什么OOP很难。由于一切都是一个对象,因此他们所做的只是要求其他对象做某事,而其他对象基本上是在做一些事情。因此,OOP程序中的控件可以在对象之间疯狂地来回跳动。

作为当前正在学习编程并在该领域遇到一些问题的人,我认为这并不是很难理解的,就像该概念的具体实现一样。我之所以这样说是因为我有OOP的想法,并且我在PHP中使用了大约一年,但是当我继续进行C#并查看其他程序员对物体的使用时,我发现许多人以这种方式这样做我只是不明白。正是这一点使我走上了对OOP原则的更好理解的道路。

当然,我意识到这个问题很可能是我缺乏对本地语言的缺乏的经验,随着时间的流逝,我会找到新的方法来利用对新程序员和我的目标一样不清楚的对象目前正在经历。杰里·科芬(Jerry Coffin)几次谈到了这一点,尤其是在他的评论中:

一方面,当您被告知OOP的一个很大的优势是更紧密地建模现实时,这变得尤其有问题,但是您首先要采取看起来像LSD启发的可怕的观点,即使是最基本和明显的部分现实。

我发现这很准确,因为看到某人为事物创建课程时,我经常得到的印象 - 一个特定的例子逃脱了我,但是我可以直接提出的最接近的是像对待距离一样一个对象(我将在下次看到引起同样混乱的东西时进行编辑)。有时,OOP似乎暂时忽略了自己的规则,并且变得不太直观。当对象产生对象时,这常常发生,这是从封装它们的类中继承的,等等。

我认为,对于像我这样的人,将对象的概念视为具有多个方面的概念,其中之一包括在否则不会将其视为对象的情况下。像距离只有一点范式转移的距离可能是一个理论上的对象,但不能握住您的手中的对象。我必须将其视为具有一组属性,而是一组更抽象的行为,例如访问其属性。我对这是我理解的关键并不肯定,但这似乎是我目前的研究所领导的地方。

当学习面向对象的编程原理(便便)时,术语是我在道路上的颠簸。当您掌握基本原理时,碎片开始就位。就像所有学习新概念的事物一样。

同意至少应与OOP平行挖掘设计模式。

对我来说,主要的跳跃只是了解OOP的抽象概念。现在,我对整个编程非常陌生,我已经编程了一年到一年半,所以我对OOP的介绍是使用ActionScript和Processing。当我第一次学习ActionScript编码时,它不在OOP中。我学会了将直接编码到动作面板中,这就是我学习编程基本基础(变量,函数,循环等)的方式。因此,我学到了它,因为直接在闪光或处理中直接做某事。

当OOP进入事物时,意识到我可以在对象内创建能够使用和重复使用的方法和属性,这对我来说很难掌握。一切都非常抽象且难以处理,但是编程语言本身要好得多,但是首先要建立这些联系的信心飞跃。

食谱

良好的理解=好的导师或好书或两者 +个人兴趣 +实践。

个人爱好

根据我的个人经验, 个人兴趣有很长的路要走,从程序编程到OOP的桥梁有很长的路要.

练习,练习和练习

我最好的朋友 为了更好地了解OOP,只有 实践。 这肯定会促进您的OOP能力。

俗话说 “没有代替努力工作,也没有成功的捷径。”

祝你好运!

许可以下: CC-BY-SA归因
scroll top