Alonzo Church的lambda演算是函数式语言背后的数学理论。面向对象编程有一些形式理论吗?
答案 0 :(得分:17)
面向对象来自心理学而非数学。
如果你仔细想想,它就像人的工作方式更像计算机的工作方式。 我们认为在 类 -ify的对象中。例如,表是座椅家具。
参加Jean Piaget (1896-1980),他研究儿童认知发展理论。 Wikipedia说:
皮亚杰在计算机科学和人工智能领域也有相当大的影响力。
他发现的一些认知概念(暗示了面向对象的概念):
分类能够根据常用功能将对象组合在一起。
类包含理解,比简单分类更先进,一些类或一组对象也是更大类的子集。 (例如,有一类叫做狗的物体。还有一类叫做动物。但是所有的狗都是动物,所以这类动物包括狗的动物)
阅读更多:伯爵的发展理论http://www.learningandteaching.info/learning/piaget.htm#ixzz1CipJeXyZ
答案 1 :(得分:5)
OOP是一种混合功能,各种语言以稍微不同的方式实现。 OOP没有单一的正式定义,但许多人试图根据声称面向对象的语言的共同特征来描述OOP。来自维基百科:
Benjamin Cuire Pierce和其他一些研究人员认为任何将OOP提炼到最小特征的尝试都是徒劳的。尽管如此,他仍然确定了在大多数面向对象语言中支持OOP编程风格的基本功能:
- 动态分派 - 在对象上调用方法时,对象本身通过在与对象关联的表中在运行时查找方法来确定要执行的代码。此功能将对象与抽象数据类型(或模块)区分开来,后者具有所有实例的操作的固定(静态)实现。它是一种编程方法,可以提供模块化组件开发,同时又非常高效。
- 封装(或多种方法,在这种情况下,状态保持独立)
- 子类型多态性
- 对象继承(或委托)
- 打开递归 - 一个特殊变量(在语法上它可能是一个关键字),通常称为this或self,它允许方法体调用同一对象的另一个方法体。这个变量是后期的;它允许在一个类中定义的方法调用稍后在其某些子类中定义的另一个方法。
答案 2 :(得分:3)
我为强烈定义和约束子类型而遇到的一个正式定义是Liskov Substitution Principle。它当然不是所有面向对象的编程,但它可以作为开发中正式基础的链接。
答案 3 :(得分:3)
Abadi和Cardelli写过A Theory Of Objects,你可能想看一下。另一个展示给出了古老的TAPL(IIRC,它们将对象作为类型lambda演算中的递归记录)。我对这些东西并不是很了解。
答案 4 :(得分:2)
我会在OO上查看维基百科的页面http://en.wikipedia.org/wiki/Object-oriented_programming它有原则,基本原则和历史。
我的理解是,它是各种语言中功能和想法的演化进程,最终与90年代推动GUI成为主流的推动相结合。但我可能会非常错误:-D
编辑:更有趣的是,人们仍在争论“是什么使得OO语言成为OO”......我不确定这个特征集是否已经达成共识,它定义了OO语言。
答案 5 :(得分:1)
历史(简化)就是这样:
首先是spagetti代码。 然后出现了程序代码(像C和Pascal)。 然后是模块化代码(在modula中)。 然后出现了面向对象的代码(就像在smalltalk中一样)。
面向对象编程的主要原因是什么?
你只能理解你是否记得历史。
首先,代码只是给计算机的一系列指令(字面意思是二进制表示) 然后是宏装配工。随着mneomonics的指示。 然后人们发现有时你会有重复的代码。 所以他们创造了GOTO。但是GOTO(或分支或跳转等)不能返回到它被调用的地方,并且不能给出直接返回值,也不能接受形式参数(你必须使用全局变量)。 针对第一个问题,人们创建了子程序(类似GOSUB)。可以重复调用并返回到调用位置的指令组。 然后人们发现,如果例程具有参数并且可以返回值,那么例程会更有用。 为此,他们创建了函数,过程和调用约定。那些在抽象之上调用的抽象称为堆栈。 堆栈允许形式参数,返回值和称为递归(直接或间接)的东西。 随着堆栈和函数被任意(甚至间接)调用的能力,程序编程,解决GOTO问题。 但随后出现了大型项目,以及将程序分组为逻辑实体(模块)的必要性。
这就是你将理解面向对象编程为何发展的原因。
当你有一个模块时,你有模块局部变量。
想一想:
Module MyScreenModule;
Var X, Y : Integer;
Procedure SetX(value : Integer);
Procedure SetY(value : Integer);
End Module.
该模块的X和Y变量是本地的。在该示例中,X和Y保持光标的位置。但我们假设您的计算机有多个屏幕。那我们现在能做什么呢?单独的X和Y不能保存您拥有的所有屏幕的X和Y值。您需要一种方法来安装该信息。这就是从模块化编程转向面向对象编程的地方。
在非面向对象语言中,您通常会这样做:
Var Screens : Array of Record X, Y : Integer End;
然后将索引值传递给每个模块调用:
Procedure SetX(ScreenID : Integer; X : Integer);
Procedure SetY(ScreenID : Integer; Y : Integer);
这里的screenid是指您正在谈论的多个屏幕。
面向对象反转了这种关系。而不是具有多个数据实例的模块(实际上是screenid在这里执行的操作),您将数据设为第一类公民并将代码附加到其中,如下所示:
Class MyScreenModule;
Field X, Y : Integer;
Procedure SetX(value : Integer);
Procedure SetY(value : Integer);
End Class.
它与模块几乎相同! 现在,通过提供指向实例的隐式指针来实例化它,例如:
ScreenNumber1 := New MyScreenModule;
然后继续使用它:
ScreenNumber1::SetX(100);
您有效地将模块化编程转换为多实例编程,其中包含模块指针的变量本身区分每个实例。得了?
它是抽象的演变。
所以现在你有多个实例,下一个级别是什么?
多态性。等等。其余的是非常标准的面向对象的课程。
重点是什么?关键在于,面向对象(如程序,如子程序等)并不是从理论的角度发展而是从许多编码人员几十年左右的实践中发展而来。它是计算机编程的演变,是一种不断的演变。
答案 6 :(得分:0)
通过比较JAVA和C#之间的相似性,IMO可以找到成功的OO语言的一个很好的例子。两者都非常受欢迎且非常相似。虽然我认为通过查看Simula67可以找到最小OO语言的一般概念。我认为面向对象编程背后的一般思想是,它使计算机看起来更像是人类,这得到了继承之类的东西(类#34;山地自行车"" road)自行车"属于父母类"自行车",并具有相同的基本功能)。另一个重要的想法是,对象(可以是可执行的代码行)可以像变量一样传递,有效地允许程序根据某些标准编辑自己(尽管这一点很有争议,我引用了改变每个实例的能力)基于一个比较的对象)。另一个要点是模块化。由于整个程序可以像变量一样有效地传递(因为所有东西都被视为一个对象),通过简单地修改被调用的类或方法来修改大型程序变得更加容易,而且不必修改main方法。因此,扩展程序的功能可以变得更加简单。这就是为什么网络企业喜欢像C#和JAVA这样的语言(完全成熟的OO)。像C ++这样的游戏公司,因为它为他们提供了一些命令式语言(如C)的控制和一些面向对象的功能(如C#或JAVA)。
答案 7 :(得分:0)
2000年,在我的学位课程中,我提出了这个模型;很快:
y + 1 = f(u, x)
x + 1 = g(u, x)
其中:
正式它与有限状态机非常相似,但区别在于U,Y,S不是有限的,而是无限的(可数)而且f和g是 Touring Machine (TM)。
f和g togheter形成 类 ;如果我们添加一个初始状态x0,我们有一个 对象 。所以OOP不仅仅是TM TM,而是OOP的特定情况。请注意,状态x与状态"内部"不同。 TM。在TM内部没有副作用, 副作用 的x状态计数。
答案 8 :(得分:0)
面向对象有点用词不当,我并不认为类或类型系统与OO编程有很大关系。艾伦·凯(Alan Kay)的灵感来自生物学,而真正重要的是交流。更好的名称是面向消息的编程。有关消息传递的理论很多,例如Pi演算和actor模型都具有严格的数学描述。那真的只是冰山一角。
答案 9 :(得分:-1)
Petri网怎么样?对象可能是 place ,组合为 arc ,message为 tokens 。我不是非常彻底,所以可能存在一些我不知道的缺陷,但你可以调查 - 有很多与Petri网有关的理论工作。
我发现了这个,例如: