同济BBS科学文化电脑技术 → 单文区文章阅读

单文区文章阅读 [返回]
发信人: flyfuture (飞未来), 信区: programming
标  题: 第 一 章    何谓物件 (OBJECTS)
发信站: 同舟共济站 (Sat Oct 14 22:29:46 2000), 转信

发 信 人∶Bird Bird                回信地址∶Bird_Bird.pbbs@bbs.nju.edu.cn
信区名称∶Programming视图C         信件日期∶Thu, 25 Dec 1997 17:43:57
信件提要∶物件导向的天空
原发信站∶PowerBBS NJU Station
------------------------------------------------------------[5718/8125]-------

                           物件导向的天空
                                                              □林俊杰

第 一 章    何谓物件 (OBJECTS)

  物件的原文是Object,国内也有人把他译为「个体」,「项目」、「目的」
等等,但为统一起见,在本文中一律统称物件。而以物件为基础的软体设计哲学
,则一律冠以「物件导向」 (Object Oriented,简写为OO)的头衔。故物件导向
程式设计便称OOP  (Object  Oriented  Programming  ) 物体导向分析(Object
Oriented  analysis, OOA),物件导向程式语言(Object Oriented Programming
Lagnage,OOPL)如此类推,不一而足。然而,到底物件是什麽呢?电脑学家给它
一个定义:

  一个抽象体、概念、或是一个有明确界定□围的事物,并且在我们要解决的
    问题中是有意义的。

  举两个例子:笔者有部脚踏车,这是个物件,阁下手上看的建青也是个物件
。生活中形形色色的事物也都是物件,阁下亦复如此。这点概念大家都可以接受
,但光定义物件没用,车子依旧在路上跑,和阁下的程式毫不相涉。再进一步去
研究,笔者的自行车是以铝合金为车骨,轻且不生□,而且它可以前进,可以刹
车,这也都没啥奇怪,但经由以上的描述,我们已经定义出笔者的自行车,和它
的特性(铝合金车架),及它的功能(前进、刹车)。当然这样可能尚未臻周延
,因为我没说我的车子有轮子,但我的程式或许不必知道那麽多!假定读者你也
有部脚踏车,你的脚踏车的车身是塑胶制的,同样的,您的车也可以前进、刹车
!理所当然,你的车也是个物件!上面提到笔者的及阁下的自行车,但其它的张
三李四也会有自行车,其中有铁的,也可能有纸糊的!此时我们可定义一个叫「
自行车」的「类别」(class)。类别也同样有个定义:

  对於具有类似性质、相同的行为、意义及共同关系的物件之描述即为类别。

  浅白的说,类别即是具相同性质物件的集合;反之,对於类别而言,物件则
为其「案例」(instance)。

  传统的软体设计方式是将问题的对象分析之後,采取适当的资料结构来表示
,并以相对的程序函数演算法来处理资料,两者看起来似乎独立而无关。而现在
我们则以「物件」将相关的资料和程序结合成一体,使得两者的关系看起来更明
白,这是物件导向程式设计最大的特点之一。

  资讯隐藏(information  hiding),也就是物件的封装性(encapsulation),
可以明白分出物件可以被外界使用的特性及受保护的内部特性。把特性依存取权
限分类可以避免程式的其它部分误用此物件,而导致不良的副作用。关於封装性
在第六章有更深入的讨论。

  Cox 氏认为我们可以藉由建立物件程式库来达成软体IC的目标,理由是因为
物件具有重覆使用性(reusability),而继承(inheritance)则是达成重覆使用的策
略。叫它继承可能有些语意不明,不过却很贴切,以自行车这个类别来说,加装
一具马达就成了一部电动机踏车,电动机踏车依然可以前进、刹车,也有车身材
质,只不过多具马达,因此这个电动机踏车类别便是由脚踏车遗传而来的。继承
在视窗的设计上特别有用。由最基本的视窗可以衍生出可卷页的,可放大缩小的
.....等等各式各样的视窗。详细的内容在後面的章节有更深入的介绍。

  火车、汽车、机车都可以为人所驾驶。「驾驶」这个动作是个相当抽象的名
词,火车、汽车、机车的驾驶方法都不一样,但驾驶一词涵盖了实际上具有差异
性的驾驶行为。这种特质称为「多形性」(polymophism)。

  另方面,光知道物於物件的特性实在不足以解决我们的问题,如何将物件引
入软体设计中呢?如何分析物件?如何遗传?如何描述一整个系统中物件和物件
间的关系?这些还都是未知的问题。在後文中,笔者将以相当篇幅讨论物件方法
论。在这个领域中应首推布奇(Booch)的研究成果,他有效的以图表分析出物件
的结构及关联。不过我并不打算多谈,因为他的理论较偏重於传统的设计理论,
对於遗传等先进的概念显得较薄弱,笔者将以劳恩森 (Lorensen) 等人所提出的
OMT ( Object Modeling Technique ) 为骨干。这套理论有一套极完整的发展过
程。OMT是他们用以发展软体的方法,因此在实作方面的效果相当理想。

  物件导向软体工程有项特点,就是试图以建立「模型」的方式来分析问题。
OMT法尤甚,它以三种基础模型来叙述整个软体的结构、运作模式,它们分别是


□物件模型(Object Model)

  描述物件的结构及物件间的关系

□动态模型(Dynamic Model)

  系统的状况时时都有变化,动态模型以事件发生和状态的改变来描述系统中
    的交互作用。

□功能模型(Functional Model)
入软体设计中呢?如何分析物件?如何遗传?如何描述一整个系统中物件和物件
间的关系?这些还都是未知的问题。在後文中,笔者将以相当篇幅讨论物件方法
论。在这个领域中应首推布奇(Booch)的研究成果,他有效的以图表分析出物件
的结构及关联。不过我并不打算多谈,因为他的理论较偏重於传统的设计理论,
对於遗传等先进的概念显得较薄弱,笔者将以劳恩森 (Lorensen) 等人所提出的
OMT ( Object Modeling Technique ) 为骨干。这套理论有一套极完整的发展过
程。OMT是他们用以发展软体的方法,因此在实作方面的效果相当理想。

  物件导向软体工程有项特点,就是试图以建立「模型」的方式来分析问题。
OMT法尤甚,它以三种基础模型来叙述整个软体的结构、运作模式,它们分别是


□物件模型(Object Model)

  描述物件的结构及物件间的关系

□动态模型(Dynamic Model)

  系统的状况时时都有变化,动态模型以事件发生和状态的改变来描述系统中
    的交互作用。

□功能模型(Functional Model)

  功能模型是OMT包容传统软体设计的一部分。它藉由资料流程图(Data  Flow
    Diagram,DFD)来描述资料转换或计算之流程。关於DFD,读友可参考建青
    94期笔者拙作「软体设计的思维」一文。

  OMT的软体设计步骤是分析(Analysis)、系统设计(System Design)、物件设
计(Object  Design)在来是实作(Implementation)之本质则是以物件观点建立前
述三种模型,再加以设计、统合、然後映射成为程式码。

  藉由物件导向的方式来设计软体可以有效的提升软体设计的效率,(虽然在
由旧方法转入物件导向时可能会有降低的现象)。举个明显的例子:Borland 公
司在Quattro推出半年多後推出Quattro Pro,三个月後视窗版就问世了。这麽快的
速度完全是拜物件导向法所赐,也使Borland公司大赚其钱(该公司号称年成长
率百分之两百)。以生产dBASE著名的安信达公司在dBASE III推出数年後才推出
dBASE IV 1.0版,而且还是伴随一堆Bug上市的。最後,在几个月前Borland终於
并吞了安信达!

1.2 物件模型(Object Model)

  物件必定具备两个基本的构要素:属性(attributes)及行为(behavior),也
就是物件的运作(operation)。再举前面的例子,自行车类别中关於车身材料等
等静态的资料就是属性,而自行车可以做的动作,如前进、煞车等等都属於属性
  在Link链结的部分,我们的案例(instance)是张老师和王同学,但老师可能
是赵钱孙李,同学也可能是周吴郑王。将两个案例一般化後,我们得到两个单纯
抽象的类别;老师类别(class teacher)及同学类别(class student)。各同学各
老师之间链结的集合便称为关联(associations)。也就是说,链结是真实世界中
物件的关系,而是将链结抽象化,一般化後我们便可得到关联(association)。

  读者在此应先建立一个概念,物件导向的分析规则是由特殊到一般,由实体
到抽象,就像我们先以张老师和王同学为研究样本,再将他们的关系抽象化。往
後还有更多的例子。

  一个老师所施教的对象通常有许多位学生而不只是一位。此时,这个教导的
关系便成一对多(one-to-many)的关系,如图1.2所示。而若一个学生只向一位老
师求教,教导关系则为1对1(one-to-one);若一个学生不仅仅只有一位老师,教
导关系就成了多对一了!请读者试著看懂我们所用的图形表示法,并且比较其间
的差异。在真实世界中,关系是相当具多样性的。例如说它可能是个选择性关系
(optional association)。例如在一夫一妻制国家中,一个男人可以选择单身(
无妻)或有唯一的配偶,如图1.3所示。但中国古时候是行一夫多妻制的,穷汉
子可能一个老婆都没有;市井小民或许只养得起一口子;天子王侯可能就藏娇无
数了!这就如图1.4所示了。图1.3中的关系是1或无,图1.4是无或许多。笔者在
此特别声明我绝对没别的意思。

  关系(association)也可以不只限定於二元关系(binary  association),它
可能是三元性(ternary  association)或多元性的。图1.5 表示老师、学生及教
室的三元关系。

1.2.3  链结的属性(Link attributes)

  前面所提到的链结都蛮单纯的,但真实情况中,链结可能有条件或□围上的
限制。例如在一个多使用者(multi-users)的作业系统(operating  system)中,
每个user对档案的存取都有不同的权限,这点在93期建青笔者拙作「切开MS-DOS
」中有介绍,各位看官可翻阅参考一下。使用者依其层级不同,可以读写档案,
或仅能读档,甚至连沾边的机会都谈不上。这麽做的理由是为了保证档案的安全
所设的规定。此时User这个物件在对於档案物件的存取关系中,便具有存取权的
属性。如图1.6所示。

  一个较特殊的链接属性称为资格(qualificiation)。可将其视为是具有逻辑
性的属性。例如关卡的通行许可。「通行」只有准许及拒绝的判定,不可能只允
许前脚进,後脚出,身体跨在门中间。因此这种关系是「资格」的判定问题。

1.2.4  集合(aggregation)

  「集合」表明了一种物件组成的关系。例如汽车物件是由轮子物件、引擎物
件、齿轮箱物件,车壳物件等等物件所组成的集合体。如果A物件是B元件的一
部分,B物件是C物件的一部分,则B物件亦会是C物件的一部分。则A物件是
C物件的一部分。A物件是B物件的一部分。则B物件必非A物件之一部分!

  这个概念在视窗设计上也很有用!你可以利用按钮物件和视窗物件组合成一
个对话盒物件。集合关系(aggregation)很容易就和遗传或其他特性搞混了,读者
宜注意。

1.2.5  遗传(Inheritance)及归纳关系(Generalization)

  我相信只要是对物件导向稍有接触的朋友都必定对「遗传」(inheritance)
这名词不陌生。遗传和归纳关系提供了程式码重复使用的可行方案。由生物学的
观点来看遗传:子代的特徵都来自於亲代。由电脑的观点来看遗传:遗传就是类
似软体元件共用,并且分享相同的行为以及相似的特性或运作。一个被遗传的父
代类别  ( parent class ) 被我们称为「超级类别」(super class)。而子代类
别(child  class)被称为副类别(subclass)。父类别和子类别之间则存在有归纳
关系(Generalization),而同时也是表示”is-a”或”a-kind-of”的关系,这
代表什麽呢?子类别的案例(instance)同时也必须是父类别的案例。这项特性十
分的合理,假定子类别被修改的和父类别不同,悲剧将无可避免的产生:适用於
父类别的运作(operation)无法正确的适用於子类别上,而设计者在不知情的状
况下,软体可能会当掉或失误。但子类别并非不能修改。你可以修改(refine)及
增加(append)一个子类别的属性(attribute)及运作(operation)之内部方法   (
method ) ,请读者回忆前面章节曾说明过运作和方法的差异。运作(operation)
是一个动作的「签名」(signature),也就是某一动作的名称。但笔者在此所说
的修改,是属於「机能性」的修改,意谓为了适应新物件的运作方式,而必需修
改其内部的方法(method),以符合新的要求,但该方法最後所要达成的目的应该
和旧方法是一致的,非重新定义。例如我们把”+”定义为运算上的加法,而你
却要定义为减法,这不是挺危险的吗?不幸地,目前的程式语言并不会主动地警
告设计者这个潜在的危险,而成为一个软体陷井。

  刚才我们曾讨论了一个重点:为了适应新物件的新特性,而必需修改其内部
的方法,但运作的签名(signature)却必需维持相同,这种特称性便为「凌越」
(overriding),但和C++中的「多重载入」(overloading)并不相同,请读者自行
比较。

  在此举一个□例。在一个几何绘图的程式中,我们尝试提供点、线、弧线、
多边形、圆形的绘图元件。在此□例中,笔者将以物件分析(OOA)中关於物件模
型的方法来分析这个例子。

  我们先试著描述这个绘图系统的各种图形元件(先分析案例)。因为用文字
说明占去篇幅繁浩,故把各物作类别的特性列於图中。决定各类别後,得视情况
将类别多馀的,无效的属性或运作剔除,并且将一些可以做成物件的特徵独立成
为物件(不过在□例中似乎没有)。下一步是□别物件与物件的关系(link),单
就这些物件来看也缺乏关联。接下来,观察这些物件是否用了一些共同的特徵(
属性及行为),将共用的特徵萃取出来,形成父类别。在□例中,我们可以先将
物件分成三类,分别是零维、一维及二维图形(用generalization),而且一维及
二维图形可以按比例(scale)伸缩,但三维图形中间空白部分则可以填色(fill)
还可以把颜色、位置、移动....等等特徵归纳成一个最终的父类别,也就是
图形(figure)类别。如此我们又得到一张新的参考图1.7。同时,在此也可以考
虑引用旧的物件。

  在图中,我们发现物件显示(display)的功能被凌越(overriding)了!为什
麽呢?因为画法不同啊!但图形(figure)那个类别要干啥呢?一点用也没有!但
他可以表示各subclass的共同特性。任何类别只要有一个运作是抽象的
(abstract),这个类别就是一个抽象类别(abstract class)。抽象类别不能产生
案例(instance),但却可供为遗传的父类别。相对於抽象类别的是实体类别,实
体类别可以衍生子代,也可以产生案例(instance)。

  另一个争议是应该遗传几代。遗传太多代可能会使子代不好懂。太少嘛,不
太合乎经济效益,二、三层很好,六、七层勉强接受、十几层恐怕令人咋舌了。
为什麽呢?是这样的,理论上类别应该可以被无穷的遗传,产生新的类别,但是
常常发生在遗传数代後的子类别的特性竟然「变质」了!父代类别的旧属性或是
旧运作变得罗唆多馀了,如果你继续引用遗传,那可能会变得没有效率,因此,
笔者认为物件重复遗传的次数应该会有一个自然上限,但这个上限是几层呢?这
就和你所设计的物件好坏有关了。

1.2.6  多重继承(Multiple Inheritance)

  前面所提到的都是单源继承(single inheritance),十分单纯,相较之下,
多重继承允许一个物件同时继承许多不同物件的特性,这种方式更接近人类思考
的方法,不过相对也产生不少问题。所谓多重继承即是一个子物件可同时继承许
多父类别,通常我们叫这种子类别为「联合类别」(join class)。

  多重继承最常引发的麻烦便是「模□两可」(ambiguity) 的纷争。这肇因於
父类别中的属性或运作可能具有类似的签名。这种情况无法以程式语言的特性避
免(虽然某些程式语言可以设定继承的优先顺序),程式设计师应该要尽力避免
模□两可的问题。另外值得注意的一点是某些较旧的物件导向程式语言(OOPL)并
不具备多重继承的特性,例如:Smalltalk-80,C++ 1.2,Objective-C。

1.3 集合与其它关系的比较

  物件与物件之间的关系是极令人感兴趣的,一个程式不太可能仅由一些简单
的物件架构而成。前面笔者曾说过集合(aggregation)很容易和其他种类的关系
搞混,在这节中,我们将讨论它们有啥差异。读者在往下看之前,不妨自己先比
较一下,看看自己是否也搞混了。

1.3.1  集合和关系(association)的比较

  集合是关系(association)一种特例,但集合关系却特别指出某个特定物件
是由那些物件组成的。就好比一部机器与组成它的螺丝钉之间的关系。主要的判
定方式是:如果一个物件是另一个物件的组成元素,那麽便存在「集合」的关系
了。

1.3.2  集合和遗传(Inheritance)的比较

  集合和遗传并不一样。遗传关系通常被称为”is-a”或”is-kind-of”(是
一个,是一种),理由前面已经讲过了,而集合则被叫做”a-part-of”(一部
分)。

  不过,有时我们最好选择集合关系来替代遗传的运用。先举一例。串列结构
(list)是资料结构中一种储存资料的基本方法,而堆叠(stack)是一种 FILO (
first in ,last out ) 先进後出的结构,关於这方面请读者自行参考与资料结
构有关的书籍。串列有些基本的运作方法,例如说:增加节点,删除节点等等。
现在我们要实作堆叠,而堆叠有自己惟一的存取方法也就是它的运作——推入
(push)和弹出(pop)。我们可以采取两套策略来获得「堆叠」类别。第一:由串
列遗传出新的「堆叠」类别,但注意!那些删除节点之类的运作(operation)也
会被遗传下来,然而对堆叠来说,不但不需要这些多馀的运作,也不能要,因为
可能意外地删除节点。因此建议采第二种策略:把串列和堆叠以集合
(aggregation)连起来,就是说把串列变成堆叠的一部分。如图1.8所示。

  关於物件模型(object model)的部分就介绍到此,由於物件模型是最基本而
重要的一部分,读者宜多留心。

--
※ 来源:.同舟共济站 cs.tongji.edu.cn.[FROM: 192.168.7.12]
[返回单文区目录]

  
Powered by wForum Version 0.9
阿卡信息技术(北京)有限公司 & KBS 开发组 版权所有 2005-2006
wForum @zixia.net , 页面执行时间:509.056毫秒