level 5
OO三步曲作者:倪 硕提交者:eastvc 发布日期:2003-11-7 8:59:00原文出处:http://nishuo.35123.net/前言:面向对象程序设计(Object-Oriented Programming,以下简称OOP)是一种起源于六十年代的Simula语言,发展已经将近三十年的程序设计思想。其自身理论已经十分完善,并被多种面向对象程序设计语言(Object-Oriented Programming Language,以下简称OOPL)实现。如果把Unix系统看成是国外在系统软件方面的文化根基,那么Smalltalk语言无疑在OOPL领域和Unix持有相同地位。由于很多原因,国内大部分程序设计人员并没有很深的OOP以及OOPL理论,很多人从一开始学习到工作很多年都只是接触到c/c++,java,vb,delphi等静态类型语言,而对纯粹的OOP思想以及作为OOPL根基的Smalltalk以及动态类型语言知之甚少,不知道其实世界上还有一些可以针对变量不绑定类型的编程语言。而这些对比却是深刻理解OO理论的重要部分,而国内这方面的资料也为数不多。故把自己的一些OO学习心得写下来做为一个系列文章(一共三篇,第一篇描叙OOP的一些基本但容易被误解的理论,第二篇主要说明各种OOPL演化和发展以及对于OOP理论的支持,第三篇主要是说模式和组件在OOP中的地位以及展望OOP的未来),由于文章描叙的只是自己对于OOP/OOPL的理解,错误以及浅薄之处再所难免,只是希望对大家能起到抛砖引玉的作用。 浅析OO的基石 从抽象说起 Booch曾经在他自己的OO领域内的名著[Booch 94]中开篇就论叙到了复杂性是软件开发过程中所故有的特质。而人们处理复杂性的最根本武器就是抽象。广义的抽象代表的是对复杂系统的简化描叙或规格说明,为了突出系统的本质属性而故意忽略其中的非实质性细节。“一个概念只有当能被最终用来实现的机制独立的描叙,理解,分析时,才将这个概念限定为抽象的概念”。而Booch也给出了他心目中关于OO领域内的狭义抽象定义:“抽象表示一个对象与其他所有对象相区别的基本特征,因此提供了同观察者角度有关的清晰定义的概念界限。”因此,根据不同观察角度,我们可以针对OOP给出不同级别的抽象层次。通常,面对一个典型的面向对象程序,[Budd 2002]将其分成五个抽象层,分别覆盖了OOP中的分析,设计与编程的各个阶段:1, 最高级别的抽象层上,程序被看成是由很多相互作用并且遵守契约的对象所组成的对象集合。对象之间相互合作完成程序的计算任务。这个抽象级别上的典型代表就是设计模式思想(Design Pattern)。2, 第二个抽象层就是一个对象集单元,也就是一群定义之间有相互联系的对象,在程序设计语言级别来看Java中是packages,C++中是name space。这个抽象级别上的典型代表就是模块化思想(Modularity)。3, 第三个抽象层所代表的是典型的OOP模式:客户/服务器模型,这主要是用来抽象两个对象之间的互交过程。在这个抽象级别上的典型代表就是对象之间的消息机制(Message Passing)。4, 第四个抽象层就是针对一组相似对象定义一个类作为生成对象的模板,类定义了对象的对外使用接口以及继承对象所需的内部继承接口,而这个抽象层次的典型代表就是接口编程(Interface Programming)。5, 第五个抽象层就是实现一个类所需要的方法和成员变量的实现(Implementation)。在这里OOP最终和POP(Procedure-Oriented Programming)相融合。当然,我们可以根据各自的观察角度划分成更细的抽象层次比如说针对第五层抽象用到的POP理论,我们还可以进一步的划分出控制抽象(三种完全描叙图灵机计算模型所需要的控制结构)以及数据抽象(ADTs)等等,并由此继续下去(如果你的想象力足够丰富的话:)。什么是OOP?OOP的许多原始思想都来之于Simula语言,并在Smalltalk语言的完善和标准化过程中得到更多的扩展和对以前的思想的重新注解。可以说OO思想和OOPL几乎是同步发展相互促进的。与函数式程序设计(functional-programming)和逻辑式程序设计(logic-programming)所代表的接近于机器的实际计算模型所不同的是,OOP几乎没有引入精确的数学描叙,而是倾向于建立一个对象模型,它能够近似的反映应用领域内的实体之间的关系,其本质是更接近于一种人类认知事物所采用的哲学观的计算模型。由此,导致了一个自然的话题,那就是OOP到底是什么?[D&T 1988][B.S 1991] .。在OOP中,对象作为计算主体,拥有自己的名称,状态以及接受外界消息的接口。在对象模型中,产生新对象,旧对象销毁,发送消息,响应消息就构成OOP计算模型的根本。
2006年01月22日 04点01分
2
level 5
people a;man b=new man();a=b;这样的代码将首先把b对象进行切割,然后再存储到a对象空间去。然而这并不是我们所期望的。那么,为了支持OOP的继承,多态,替换原则,但却需要避免对象切割的发生,面对对象a我们将采用何种分配空间模型呢?常用的有下面三种方式:1, 只为a分配基类people的存储空间,不支持对象多态以及替换原则。这样的模型内存分配紧凑,存储效率很高。2, 分配继承树中的最大类对象所需要空间(在这里是man类的对象值空间),这样的模型简单,同时可以实现多态和替换原则而避免对象切割问题,但是十分浪费内存空间十分明显。 3, 只分配用于保存一个指针所需要的存储空间,在运行时通过堆来分配对象实际类型所需要的空间大小,这样也可以实现多态和替换原则而避免对象切割问题。(也就是说a只是一个对象的引用,而不是真实的对象,真实对象的生成必须靠程序员显式的声明)。对于上面提到的三种内存模型,1和3都被一些程序设计语言所采用。相信说到这里,大家应该开始慢慢明白了。是的,C++作为C语言的继承者,对于效率的追求迫使它必须采用第一种最小静态空间分配的方式,由于基于栈空间的程序运行效率要比基于堆空间的程序运行效率高出许多,所以C++允许用栈空间保存对象,但同时也允许堆空间保存对象,可以说C++是采用了1和3两种相混合的内存模型,而C++中基于1内存模型的对象,也就是说基于栈内存空间的对象是没有办法体现多态和替换原则的(请思考一下在C++中什么对象是基于栈的),而基于3内存模型的对象将支持多态和替换原则(又想一想在C++中什么对象是基于堆的)。这里,我们终于可以揭开第一层迷雾了,很多人都知道在C++中只有指针和引用才能支持对象的多态行为,但是为什么会如此?上面做出了最好的解释。Java语言由于设计理念和C++有着很大的区别,它采用的是第3种对象模型,一切对象(除了基本类型对象)都是基于堆分配的。这也是Java语言必须采用虚拟机的原因所在。在C++中很大一部分对象是不需要程序员进行管理的(静态空间对象),而在Java中,如果不采用虚拟机机制,所有的对象都需要程序员管理,而这样的开发代价将是巨大而不现实的。这也就揭开了第二层迷雾,当我们在对比C++和Java语言的时候总是为虚拟机是否有其价值而争论不休,但当你抛开所谓的好与不好的简单讨论,进入到其语言本身的内在对象存储本质的时候,也许对于各种声音才会有一个属于自己的清醒认识。让我们继续望下走,不同的对象内存分配模型直接影响到其程序设计语言的赋值的含义。在各种编程语言中,赋值可以给出两种不同的语义解释:复制语义和指针语义。很明显,由于C++支持两种相混合的对象存储模型(但是默认的存储方式是栈存储),所以在C++中默认赋值语义采用的是前者,但C++同时提供了指针语义的功能支持(在拷贝构造函数和=运算符重载中用户进行自定义)。而在Java中采用的是后者。这也就是我们揭开的最后一道迷雾,不同的对象存储模型直接导致了不同的赋值语义。面向对象的计算模型和可计算性 编程就是用计算所需要的指令构成一种运算装置,无论我们的程序设计思想以及程序设计语言如何发展和提高,最终我们所使用的底层计算数学模型并没有改变。但高级程序设计语言给我们带来的变革是在其语言环境中构建起了一个全新的,更抽象的虚拟计算模型。Smalltalk语言引入的对象计算模型从根本上改变了以前的传统计算模型,以前的计算模型突出的是顺序计算过程中的机器状态,而现在的对象计算模型突出的对象之间的协作其计算结果由参加计算的所有的对象的状态总体构成。而由于对象本身具有自身状态,我们也可以把一个对象看成是一个小的计算机器。这样,面向对象的计算模型就演变成了许多小的计算机器的合作计算模型。图灵机作为计算领域内的根本计算模型,精确的抓住了计算的要点:什么是可计算的,计算时间和空间存储大小开销有多大。计算模型清楚的界定了可计算性的范围,也就界定了哪些问题是可求解,哪些问题是不可求解的。OOP为程序员提供了一种更加抽象和易于理解的新的计算模型,但其本身并没有超越冯.诺依曼体系所代表的图灵机数学计算模型。所以我们不能期望OOP能帮助我们解决更多的问题,或者减少运算的复杂度。但OOP却能帮助我们用一种更容易被我们所理解和接受的方式去描叙和解决现实问题。
2006年01月22日 04点01分
5
level 5
结 束 这篇文章做为这个系列的第一篇,对于OOP中的许多核心概念和机制进行了有益的讨论,作者衷心的希望通过这篇文章能够让大家对于OOP有更深入的理解,同时明白OOP作为已经发展将近三十年的程序设计思想,其自身丰富的理论内涵不是单单学习几门OOPL就可以领悟。最后期望本文能实现了它的初衷---抛砖引玉。Reference: [D&T 1988] : Type Theories and Object-Oriented programming by Scott Danforth and Chris Tomlinson on ACM Computing Surveys Vol.20 No.1 March 1988 [Liskov 1988] :Data Abstraction and Hierarchy by Barbara Liskov on Sigplan Notices,23(5),1988 [C&W 1985] On understanding types,data abstraction,and polymorphism by Cardelli . L and Wegner . P on ACM Computing Surveys Vol.17 No.4 Dec 1985 [B.S 1991] What is “Object-Oriented programming”?(1991 revised version) by Bjarne Stroustrup AT&T Bell Lab Murray Hill ,New Jersey 07974[B.S 1998] 《The C++ programming language (Special Editon)》 by Bjarne Stroustrup Addison Wesley 1998 [Gamma 1995] 《Design Pattern》by Eric Gamma etc Addison Wesley 1995 [Booch 94] : 《Object-Oriented Analysis and Design with Application (Sec Editon)》 by Grady Booch Addison Wesley 1994[Jams 2000] : 《The Java programming language (Third Editon)》by Ken Arnold, Jams Gosling, David Holmes Addison Wesley 2000 [Budd 2002]: 《Introduction to Object-Oriented programming (Third Editon)》 by Timothy A.Budd Addison Wesley 2002 参考书籍:《C++程序设计语言》Bjarne Stroustrup著 裘宗燕译 机械工业出版社 2002年 《设计模式》Erich Gamma等著 李英军等译 机械工业出版社 2000年 《面向对象软件开发原理》Anton著 袁兆山等译 机械工业出版社 2003年 《面向对象编程导论》Timothy A.Budd著 黄明军等译 机械工业出版社 2003年 《面向对象分析与设计》 Grady Booch著 冯博琴等译 机械工业出版社 2003年 《面向对象软件构造》(英文版.第二版) Bertrand Meyer著 机械工业出版社 2003年 -完-
2006年01月22日 04点01分
6