《Delphi面向对象编程思想》前言

Delphi 面向对象编程思想

刘 艺 著

前 言

第一次知道 Delphi 并不是因为 Borland 公司的 Delphi 软件,而是在柏拉图的经典著作《柏拉图对话录》“申辩篇”中读到了这个单词。

A friend of mine . . . went to Delphi and boldly asked the oracle to tell him whether . . . there was anyone wiser than I was, and the Pythian prophetess answered that there was no one wiser . . .

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 面向对象编程的深入

Published At
Categories with Web编程
Tagged with
comments powered by Disqus