我母亲在Fortran上完成了大学论文,现在(十多年后)需要学习c ++进行流体模拟。她能够理解所有过程编程,但是无论我多么努力向她解释对象,它都不会停留。(我在Java上做了很多工作,所以我知道对象是如何工作的)我想我可能会以太高层次的方式来解释它,所以对于那些从不与它们一起工作并且成长的人来说,这真的没有任何意义。在纯粹的程序化编程时代。
有什么简单的方法可以向她解释,以帮助她理解?
我母亲在Fortran上完成了大学论文,现在(十多年后)需要学习c ++进行流体模拟。她能够理解所有过程编程,但是无论我多么努力向她解释对象,它都不会停留。(我在Java上做了很多工作,所以我知道对象是如何工作的)我想我可能会以太高层次的方式来解释它,所以对于那些从不与它们一起工作并且成长的人来说,这真的没有任何意义。在纯粹的程序化编程时代。
有什么简单的方法可以向她解释,以帮助她理解?
Answers:
简短的回答:不。
长答案:没有“简单方法”,因为OOP远非简单。过程编程全部与“变量”和“ if then goto”有关。其他所有内容都是语法糖,但是这四件事就是过程编程的全部内容。一旦获得它们,没有什么可以阻止您。
OOP是一种组织变量和代码段的方法。有多少种模式可以定义OOP?25吗 30吗 即使是从不同语言和背景学习过OOP的老师也不同意其自己的定义,所以...它怎么简单?
我不知道您是怎么想到的,但是由于您母亲的经历与我相似,所以我可以告诉您我是如何想到的。
我在一个非常大的项目中用C编程。当时是1988年。许多程序员都在组织模块和库,但要避免避免干扰其他工作并保持良好的职责分离。
我们来到了一个“解决方案”,该解决方案是将所有相互关联的全局数据放入结构中,在这些结构中放置一些需要回调的函数指针。我们以这种方式概括了所谓的io_mask
(各种文本模式对话框)graphic_manager
等。
在1996年,很容易发现这些结构被命名为“类”,而那些函数指针被成员函数和虚拟函数所取代,或者被其他更新旧项目的程序员所链接到其他对象(称为行为)。
当我开始感到对OOP的需求时,我开始了解OOP :隔离,多态和运行时定义的行为。
今天,我与OOP一起工作,但我不认为它是服务的原则:只是一个“共同的成语”(...集),它使我们可以一起讲话,而无需一直提供冗长的解释和描述。 。实际上,最重要的是“常规”。毕竟,OOP所做的只是-如果-if then goto:它只是“多层”进行。因此,抽象和成语优于成语。
别理他们。直到她感觉不到它们的需要之前,都不要尝试解释:她会觉得它们就像做简单事情的复杂方式一样。她是对的...直到她所做的-实际上-很简单。
如果只有四件事,没有人会想到“整理桌子”。当最上面的东西开始相互干扰时,这才有意义。那是OOP出现的时候了。
您不需要OOP即可使用C ++。整个C ++标准库不是根据OOP设计的(尽管它可以与OOP配合使用),并且C ++不是Java。
从我的所有经验来看,最差的C ++老师和C ++程序员都是来自Java的人,他们对所有事物的偏见都不是OOP,会使像C ++这样的语言(不是)仅适用于OOP。
让我为那些想使用C ++的人推荐一本好书:Accelerated C ++:它将带您进入C ++习惯用法,而无需假装遵循预先定义的学说。
一位老朋友声称我对OO编程的定义最短,我发现它对某些人(而不是其他人)有效:
面向对象的程序设计是带有观点的数据。 您不移动椅子,而是要求椅子自行移动。您不对列表进行排序,而是要求它对自身进行排序(可能带有提示)。等等。
这样做的目的是让人们以不同的方式思考程序内部如何完成事情。
告诉她想像现实世界中的物体之类的物体。例如,整个世界可能是面向对象的程序设计(在C ++中)与某种功能性程序设计(可能是用上帝的语言Lisp完成)的混合体。
以一个物体为例,例如割草机,它具有一定的属性,并且可以做某件事。(对象和类)
然后告诉她一个更好的割草机,这是您现有割草机的扩展。告诉她更好,但仍建立在相同的机制(继承性)上。
然后告诉她关于你自己的事。告诉她,有时您可以成为割草专家,但实际上您是一名程序员,并且以谋生为生。就像您同时充当两个不同的实体一样。这是多态性。
等到她明白了,再告诉她如何用她必须学习的语言(C ++)来实现这些东西。
然后告诉她,如果她必须在计算机世界中编写这个世界的模拟,那么她将必须学习如何做到这一点。
当她知道如何将她对现实世界的想法转化为程序代码时。她将学习如何使用面向对象的编程语言进行编程。
我已经从汇编程序和COBOL转到了Ruby。
最初帮助我的实际上是忽略了创建实例的类的概念。
只需从代码开始。有一个类,但是只有类级别的方法。在方法中,很多东西与参数,变量,条件,数组,字符串,布尔值等有关。这些东西应该很熟悉。
因此,在这一点上,该类可以看作是作为目的来放置所有相关方法的地方。将其称为容器或库对她来说将更为熟悉。
显然,必须对代码进行分段以使其易于管理,因此您将在每个区域中拥有一个。例如,要在PC上管理一组实用程序,您可能有一个计算器类,可以在其中将计算器的所有代码放在一个地方。如果您的电脑上只有1个计算器,则类级别的方法就足够了。
那是一个开始。
好的,现在考虑您要打开多个计算器并更改每个计算器的外观以及它在屏幕上的位置这一事实。所以现在您不能只拥有像'screen_location'这样的计算器方法,因为您有多个方法,并且每个实例都有自己的位置...每个实例...好的,所以我们需要实例。
注意:我的术语来自ruby而不是c ++,因此您可能需要翻译。
我将分两个步骤或四个步骤来解释它,具体取决于您想拆分概念的程度。
步骤1:将她介绍给建筑物。从Fortran数据类型到结构,这仅是很小的一步。步骤1a:确保她了解动态内存分配和指针。
步骤2:添加仅与那些结构关联的过程。步骤2a:在构建“包裹”较小结构的较大结构的基础上添加继承。
对于Fortran程序员来说,“哇”的因素是编译器需要跟踪很多东西。对。那就是编译器的用途...
一旦她了解了结构,我认为下一个关键点将是认识到面向对象编程是将事物可以传递给的方法集限制为可以实际应用于该方法集的一种手段。事情。
在非面向对象的编程中,如果一个树和一个LinkedList使用不同的数据类型,则必须使用不同的方法向每个树添加节点。非面向对象的语言一般会发牢骚如果试图命名这两种方法AddItem
,因为任何给定的名称,只能是指一种方法,从而导致一个以创建像方法名AddTreeItem
,AddLinkedListItem
,RemoveTreeItem
,等这种方法的作品,但它是一个有点丑陋。从概念上讲,方法AddTreeItem
和RemoveTreeItem
似乎属于同一类,但名称却不是那样。人们可以为重写的名字TreeAddItem
,TreeRemoveItem
,LinkedListAddItem
等等,但是这会在每次方法调用的开始时带来很多“冗余噪音”。典型程序中的绝大多数方法调用将具有三个基本信息:(1)源代码的哪一部分包含该方法;(2)正在使用本节中的哪种方法;(3)正在处理什么数据?在许多情况下,所作用的数据类型足以识别该方法属于哪个代码段,因此上述部分(1)是多余的。在语句开始处以视觉方式识别材料比在其他地方更容易识别材料,因此像这样的编码/命名风格TreeAddItem(myTree, whatever)
最终将最不有用的信息放在了首位。
相比之下,使用面向对象的程序,可以将方法有效地命名为Tree.AddItem
等,而类似的语句myTree.AddItem(whatever)
将使编译器实质上说:“ Hmm ... myTree
是类型的Tree
,因此应调用此代码Tree.AddItem()
。指定Tree.
调用的时候AddItem
,因为编译器知道的类型myTree
从概念上讲,声明等。myTree.AddItem(whatever)
相当于Tree.AddItem(myTree, whatever)
,以及一些面向对象的语言可能允许这两种形式是等同的;事实上,大多数语言省略从功能规范的第一个参数,而是有在一个类中定义这样的方法Tree
隐含地采取类型的参数Tree
,并为其分配一个名称等this
,self
或Me
。
面向对象的编程语言通常包括各种附加功能,例如继承,虚拟功能等,这些功能在许多应用程序中非常有用,但即使没有这些功能,根据功能对其进行分组的功能也非常有用。