《Delphi面向对象编程思想》前言
2006-02-04 13:39:11 来源:WEB开发网Delphi面向对象编程思想
刘 艺 著
前 言
第一次知道Delphi并不是因为Borland公司的Delphi软件,而是在柏拉图的经典著作《柏拉图对话录》“申辩篇”中读到了这个单词。
A friend of mine . . . went to
Delphi和苏格拉底的智慧
Delphi是预言之神oracle居住之地。《柏拉图对话录》记载了苏格拉底的一位朋友前往Delphi向预言女神Pythian询问谁是最智慧的人。Pythian说没有人比苏格拉底更智慧。苏格拉底深感不解,因为他发现自己身边有很多政治家、诗人、哲学家和艺术家。难道这些“专家”和“权威”不是更有智慧吗?自己比起他们差多了。
苏格拉底一一拜访了这些“专家”和“权威”,却发现他们往往自以为是,自欺欺人,对自己不懂的东西也假装知晓。通过拜访,同时苏格拉底也发现自己在许多方面知之甚少。但苏格拉底并没有不懂装懂,他坦诚了自己的无知。这就是预言女神Pythian所说的真正的“智慧”。
其实这种智慧不是古希腊人最早提出来的。早在苏格拉底之前,我国的老子就已经总结过了。《道德经》中有“知人者智,自知者明”,此之谓也。
现在,我们使用的Delphi已经是一个优秀的编程语言和软件开发工具了。然而,面对博大精深、不断发展的Delphi,我们在许多方面还知之甚少。可是在学习和使用Delphi时,我们是否也具备了苏格拉底那种自知自明的态度和知所不知的智慧呢?
有许多选择Delphi的朋友,最初的想法可能是因为Delphi功能强大,易学易用。他们甚至3个月就声称精通了Delphi,半年就敢独立开发软件。其实他们所能做的工作仅仅是控件的拖拉而已。当他们为自己的程序陶醉时,实际上是在为Delphi的精巧睿智和别人的控件所陶醉。这种Delphi程序员往往被别人戏称为“拖拉”员。而他们却俨然以Delphi高手自居。
也有许多放弃Delphi的朋友,最初的想法可能是因为觉得Delphi只是一个类似VB的RAD工具。在他们看来Delphi就是控件编程,无法像C++或java那样真正实现OOP。他们怀疑Delphi是不是具备面向对象编程语言的特性、能不能实现多态、模式等面向对象的技术。在他们眼里只有使用C++或Java的人才是真正的高手。
那么,什么是真正的高手,怎样才能成为一个高手呢?
论“器”与“气”
首先让我们来看一看什么是武林高手,或许我们能够从中得到启发。
凡是喜爱武功或武侠小说的人都知道,修炼武功分为外练和内修两种途径。外练拳脚、兵器,拳脚的招式和兵器的好坏是关键;内修真气,练精化气、练神还虚是根本。这两种修炼方法的最大差别在于时间和功力的函数关系上,如图 1所示。通俗地讲,头3年,练外功的可以轻易打败练内功的;第10年,双方只能打个平手;15年后,无论你如何练外功都不是练内功的对手。20年后,内功高手天下无敌。其中的道理正是在于 “器”和 “气”的辩证关系。
“器”为有形之物,刀枪剑戟,皆为有形之器。外练武功,离不开这些有形之器,练功即为练兵器。所以使枪弄剑的武林高手往往依赖于兵器的好坏。
“气”为的无形之质,一切智慧、法力、思想皆为无形之质。内修气功,离不开这些无形之质,练功即为练气。所以真正的武林高手往往无需依赖于特定的兵器,对于他们而言,任何有形之物皆可随气所运,拟为兵器。一折扇,一拂尘在其手中威力不亚于名枪好剑,是得气所致也。
图 1两种修炼方法的时间和功力函数图
在软件开发中,编程工具是“器”,编程思想是“气”。
编程之器中,易用之器如VB、PB;难用之器如汇编、C++;古老之器如FORTRAN、COBOL;时尚之器如Java、C#。
编程思想中,又有面向对象和面向过程之分,它们既是世界观又是方法论。前者反映的是人对客观对象的思维方式,后者反映的是机器对指令的思维方式。在软件开发的不断实践中,前者的优越性已经得到不断的体现和证实。
掌握面向对象的编程思想如同获得练气的真谛。它的重要性往往胜过了对编程语言的选择!
有人即使选择了面向对象的利器,也无法成为真正的高手。因为他看重的是“器”的好坏,忽略的是“气”的修炼。
实际上“一个系统或语言是不是面向对象的并不重要,重要的是怎样才能是面向对象的以及用什么办法实现相关的好处”。(《面向对象方法:原理与实践》机械工业出版社2003年3月)
练器虽易,但难成高手。练气虽好,但见效缓慢,寂寞难耐,非一般常人可以明心见性,直取大道。所以很多武林高手都是先练器、后练气;内外兼修,终成正果。
对于初入武林的新手,他们需要借助兵器的威力,以补内力之不足,器的好坏往往很重要。但随着武功的增加,内力的勃发,对器的依赖性应该减小。《神雕侠侣》杨过练剑,起步初学时好使利剑,谙悉剑法后喜用钝剑,内功纯熟后树枝亦当剑。所以对于真正的高手而言,剑器的好坏往往并不重要。
同样,软件高手的成长也有这样的过程。初学编程需要选择好的语言,这样可以取得事半功倍的效果,同时激发兴趣,增强信心。一旦熟悉了一种语言之后,应以此为契机进而掌握面向对象编程思想。这时你熟悉的不再是语言本身的语法、函数、类库,而是绑定、多态、模式等思维方法,然后触类旁通,再学其他面向对象语言也不难。苦练内功,勇于实践,最终成功的真正的软件高手,是不受编程语言限制的。他们可能比较熟悉一种开发工具,但那也只是承载他们大道无形之气的器具。他们虚心好学,善于总结。他们的思想、方法、模式甚至哲学,既超越了编程语言,又可以指导编程语言的实践。
Delphi为软件高手的成长提供了内外兼修的捷径。学练Delphi,既可用其RAD之长,控件之利,初学起步,迅速击败对手;学练Delphi,也能以其OOP之能,VCL之强,培根固本,成就不败之功。
威震四海的华山剑派曾分为“剑宗”和“气宗”,前者只练器,讲招式;后者兼练气,重筑基。
学习Delphi好比修炼华山剑法,走RAD之路是 “剑宗”,从OOP之道是“气宗”。前者喜用控件,看中奇技淫巧;后者好为对象,热衷方法模式。前者追求速成,后者志存高远。
我认为,无论是为RAD而选择Delphi还是因OOP而放弃Delphi的朋友都没有真正了解Delphi。Delphi是一个不错的RAD开发软件,可是不学OOP,不深入VCL就很难成为真正的高手。同样,Delphi是一个地道的OOP编程工具,结合Delphi强大的RAD和高效的编译器,可以比其他OOP语言有更多的优势和更高的效率。如果能打破门户之见,“器”“气”同练,内外兼修,我相信Delphi程序员不难从一个RAD快手成长为OOP高手,最终笑傲江湖,纵横四海。
面向对象编程思想和大道无形之气
前面我简单讨论了“器”与“气”的辩证关系。在编程中,修持内功、提高内力的关键之一在于掌握面向对象编程思想。实际上,我更认为面向对象编程思想才最合大道无形之真气的妙处。
为什么这么讲?“古之大化者,乃与无形俱生”(《鬼谷子》反应第二),气的奥妙首先在于它的“大化”。大化者,天地之大造化也,集一切创造和变化之能。面向对象的编程思想具备了这种特质。
老子曰“无名天地之始,有名万物之母”,无名是无以名状,无法定义的意思。所谓面向对象的思维方式,最奥妙之处在于如何从“无名”中识别和定义对象、如何从“有名”中构造和使用对象。
对于软件开发人员来说,认识客观实体的过程、对用户需求进行分析和设计的过程,就是发现和界定对象的过程,是从无名到有名的过程。然而这里的对象又不同于面向过程中的变量或函数,对象是由类创建的,类是概念的抽象,是可以定义的“有名”,是对象之母。
于是乎,太极生两仪,两仪生八卦,通过类的继承和派生,万物始生,系统构成。
即使作为面向对象编程工具的“器”,也体现和承载了面向对象的编程思想之“气”。
号称“万古丹经王”的内功练气经典之作《周易参同契》开篇第一句话就是“乾坤者,易之门户,众卦之父母。坎离匡郭,运毂正轴,牝牡四卦,以为橐籥。”
从软件开发的角度来理解,面向对象的编程工具虽然提供了构建无穷种软件系统的可能性,但这种无限性却是建立在自身类库的有限框架之中。无论是Delphi的VCL,还是Java的类库,或是.net框架,无一不是建立在这样一个类似于周易八卦的架构之中。“易有太极,太极生两仪,两仪生四象,四象生八卦” ,这样的结构完美无瑕,有着无穷的创造力。
太极是Delphi中的TObject,它是构建系统的原子,它是所有类的祖先,它具有所有类的基本特征。在Delphi的编程世界中,根类TObject生持久对象类TPersistent,持久对象类TPersistent生组件对象类TComponent,进而为开发应用程序提供了丰富的控件和强大的功能。
然而类库的结构框架不仅仅是给我们可以作为“器用”的组件,更重要的是这种结构通过类之间的关系和相关作用,实现了“气”的构造和变化,体现出面向对象编程思想的精髓。为我们创建自己的系统提供了绝好的示范。
气的奥妙其次在于它的“生于无形”。无形意味着它的自由性、开放性、适应性。在面向对象编程思想中处处充满着 “气”的这种大道无形的智慧。
比如,面向编程对象中的多态性可以使程序员撰写更加通用的、更加开放的程序。程序员可以为Vehicle对象编写一个纯虚抽象方法Stop(),这样的通用Stop()方法与驾驶什么车无关。程序员可以让派生类去操心如何完成stop()方法,而继续在更高的抽象级别上编写自己的通用过程。即使Car对象的stop()方法与Bicycle对象的stop()方法完全不一样,程序员可以也可以使用Vehicle.stop(),多态性可以让创建的对象自动知道哪一个合适的方法将被调用。这就使程序具备了“气”的开放性和适应性。
练气功中讲究“上德无为,不以察求。下德为之,其用不休。”(《周易参同契》)
在面向对象编程思想中,“上德”是晚绑定的纯虚抽象方法、是以不变应万变的对象接口,它是对事物的高度抽象、是形而上学。“上德无为”是说在抽象层次,通过无为来体现编程“虚”的一面,因为这时还无法确定实际使用的真正对象(可能是Car对象也可能是Bicycle对象,更可能是以后发明的新交通工具对象),“不以察求”要求我们跳出具体需求的约束,不去考虑具体的实现代码。所以纯虚抽象方法或对象接口中是没有任何代码实现的。
在面向对象编程思想中,“下德”是对纯虚抽象方法的覆盖、是对对象接口的实现。“下德为之”,提供了真正的代码实现。“其用不休”,满足了不断变化的需求。
多态性使得程序员在以后不费多大力气就可以派生对象,实现程序。假设程序员在为Car和Bicycle构建应用程序,并不知道还存在Truck,但这并不要紧。程序员可以为继承Vehicle类的Car和Bicycle类撰写覆盖stop()的方法。这样,在程序中只要把创建的Car和Bicycle对象转型为Vehicle的类型,使用Vehicle的stop()方法,就可以让Car和Bicycle对象动态绑定符合自己要求的stop()方法。即使后来新增了Truck对象,仍然是调用Vehicle的stop()方法,并不需要进一步改动程序。
“物有自然,事有合离。有近而不可见,有远而可知。近而不可见者,不察其辞也;远而可知者,反往以验来也。” (《鬼谷子》抵戏第四)
虽然客观事物是复杂,用户需求是变化的,但是其中也有一定的内在规律。
近而不可见者,只看眼前的具体功能实现,不察事物的一般发展规律,心中只有孤立的数据和机械的流程,一旦“事有合离”,则措手不及,难以应对。这样的编程是静态的、机械的、难以维护和扩展的。
远而可知者,善于发现规律,重视代码重用,眼中尽是有机的对象和和谐的关系,即使需求改变,也能从容应对,游刃有余。这样的编程是动态的、灵活的、可维护和可扩展的。
Paul Kimmel在《Delphi6应用开发指南》中说“以非面向对象的方法去使用面向对象工具是一个错误。使用Delphi编写结构化程序可以很快地到达beta版……你的程序可能永远脱离不了beta版。迅速得到错误的答案,仍然是错误的。”
同样是使用Delphi,如果没有面向对象的编程思想,好比“不察其辞”,最终仍然是“近而不可见”,难以开发出优秀的系统。唯有潜心苦练,悉心总结,掌握面向对象编程思想的博大精深,才能运“气”自如,“反往以验来也”,最终达到“远而可知”的境界。
关于本书
从第一个真正面向对象的语言Smalltalk(1972年)出现至今已经有30多年的历史了。然而书店中充斥着面向对象编程的书籍大都是C++和Java,似乎面向对象的语言仅有这两种,而实际上真正的面向对象语言却有4个基本分支,近20种之多。由于Delphi面向对象编程的书籍很少,不少程序员为了学习OOP,不得不放弃Delphi。这真是Delphi的一大悲哀。当我读到Bruce Eckel的《Thinking in Java》,就感叹过为什么就没有这样的Delphi大作呢?
其实,Delphi 系出名门,她是Borland公司在Object Pascal基础上开发的。现在,Borland公司从Delphi7开始使用Delphi language来取代Object Pascal叫法[1]。Delphi 在OOP方面实际上并不比C++和Java逊色,这一点读者可以参见本书附录“面向对象编程语言比较: Java、C++和Delphi”。
为此,我一直打算写一本Delphi面向对象编程的书,总结自己在Delphi面向对象编程方面的学习体会和实践经验。然而这是一项难度不小的工作,全书从构思到下笔花费了很长的时间,直到今年5月才算正式完稿。刚巧今年也是Borland创建20周年,作为Borland产品Delphi的用户,拙作的出版也算是对此的纪念。
这是一本纯粹讨论Delphi面向对象编程的书,面向对象不是本书的时髦点缀,而是这本书的核心和全部。
本书自第1章“建立面向对象的新思维”开始就试图从面向对象编程的历史和现状入手,阐述面向对象编程思想的起源发展和基本观念,以及面向对象建模方法和UML的应用。这一章是为了帮助读者建立面向对象的基本概念,了解面向对象的思维方法。
第2章“Delphi对象模型”介绍了Delphi面向对象编程的基础知识及其对象模型结构体系。
第3章“理解对象”从对象的本质、生死、关系三方面深入讨论了对象的内部机制、生命周期、相互作用,为读者了解和掌握对象打下了基础。
第4章“使用对象”讲解了在Delphi面向对象编程中如何高效使用对象。这里重点讨论了界面对象、组件对象、对象集和对象参数的使用方法和技巧,并对VCL组件使用和开发中的常见问题进行了深入思考。
第5章“深入多态”介绍了多态的概念及其在编程中的应用。其中通过大量的实例讲解了重载和覆盖、虚方法与动态方法、抽象类和抽象方法、类的类型转换等重要概念和思维方法。
第6章“剖析接口”全面介绍了对象接口的编程知识和应用技巧。阐述了接口在实现动态绑定和多重继承方面的重要作用,演示了接口在面向对象编程中的实际用法。
第7章“研究封装”阐明了封装在面向对象编程中的重要意义和应用原则,并分别从逻辑上的封装和物理上的封装来进一步讨论封装的实现方法和应用技巧。
第8章“实现界面和业务的分离”将面向对象编程应用到一个新的高度。这一章通过界面和业务分离的演化实例,讲解了如何利用面向对象的设计将一个桌面程序进化到分布式多层系统。并接合Delphi的最新Web技术,介绍了如何用Web Service封装业务对象,用Web Form封装界面对象,用新技术封装旧对象,从而实现跨平台的应用。
最后本书第9和10章的“深入浅出VCL”,研究了VCL的内部机制,并剖析了VCL重要类系的对象用法,为渴望深入提高编程水平的读者提供了参考。
从本书的组成结构上看可以划分成5大部分。
第1部分,全书的前两章是Delphi面向对象编程的入门。已经掌握面向对象基本概念并有Delphi编程经验的读者可以跳过这两章。
第2部分,第3、4章是Delphi面向对象编程的关键。不掌握对象的实质,就无法使用好对象。
第3部分,第5、6章是Delphi面向对象编程的深入。面向对象的高级技巧无一不是建立在虚方法、抽象方法、对象接口等动态绑定机制上和向上转型、向下转型、接口转型等类型转换机制上的。
第4部分,第7、8章是Delphi面向对象编程的应用。为了实现程序的可维护性、可扩展性和可重用性,封装已经成为面向对象编程的重要思想之一。通过封装从而实现界面和业务对象的分离,从界面和业务分离逐步实现分布式多层体系结构,再实现界面和业务应用的跨平台。这里演示了基于面向对象编程思想的从一般应用程序到企业级应用程序的解决方案。
第5部分,最后的第9和10章是Delphi面向对象编程的参考。熟悉VCL学习VCL对精通Delphi十分有帮助。鉴于目前VCL的内幕资料缺乏,这一部分提供给读者的可能比较有限,但却是很难得的。
准确地讲,这本书不是写给“高手”的,而是写给那些想从RAD向OOP转变的程序员的,以及希望通过Delphi来学习OOP的朋友的。我觉得作为一本比较实用的中级Delphi技术书,比较合适。所以在全书的行文中,力求通俗易懂,图文并茂,并精心编写了大量的示例程序(随书光盘源代码超过50兆),供读者研习。这本书的核心OOP,而不是针对Delphi的所有方面。阅读本书需要有一定的Delphi基础,书中涉及到一些专门的知识(如:COM+等)还需读者进一步参阅相关书籍。
可能会有一些“高手”对本书失望。我觉得自己不适合写“高手”阅读的书,因为我就不是高手,我觉得自己永远是新手。和其他新手不同的是,我使用Delphi的时间更长一点,经验和阅历稍多一点。所以发现本书有不妥之处敬请读者指正,不尽人意之处希望多多包涵。
网友xzh2000讲得好,“一本书的生命很重要,如果作者能花心血经常修改补充,才能成就经典!”。的确一本好书需要经过多次反复修订才能成为经典之作,所以我愿意聆听所有读者的宝贵建议,并希望这本书能够不断修订再版。