当前位置:高等教育资讯网  >  中国高校课件下载中心  >  大学文库  >  浏览文档

《Thinking in Java》中文版 第一章 对象简介

资源类别:文库,文档格式:PDF,文档页数:34,文件大小:505.97KB,团购合买
我们剖析事物的本质,从中形成概念,并根据需要赋予它重要性。这 切很大程度上是源于,我们所使用的语言已经在其形式中包含了一套为它 的使用者所完全接受的规范,而我们正属于接受这一规范的那群人.如果 我们拒不接受语言在数据的组织与分类方面的原则的话,那我们根本就没 法说话。” Benjamin Lee Whorf(1897-1941) 计算机革命的推动力在于机器。于是机器的发展也左右了编程语言发展。
点击下载完整版文档(PDF)

致读者 我从2002年7月开始翻译这本书,当时还是第二版。但是翻完前言和介绍部分 后, chinapub就登出广告,说要出版侯捷的译本。于是我中止了翻译,等着侯 先生的作品。 我是第一时间买的这本书,但是我失望了。比起第一版,我终于能看懂这本书 了,但是相比我的预期,它还是差一点。所以当 Bruce eckel在他的网站上公开 本书的第三版的时候,我决定把它翻译出来。 说说容易,做做难。一本1000多页的书不是那么容易翻的。期间我也曾打过退 堂鼓,但最终还是全部翻译出来了。从今年的两月初起,到7月底,我几乎放 弃了所有的业余时间,全身心地投入本书的翻译之中。应该说,这项工作的难 度超出了我的想像。 首先,读一本书和翻译一本书完全是两码事。英语与中文是两种不同的语言 用英语说得很畅的句子,翻成中文之后就完全破了相。有时我得花好几分钟, 用中文重述一句我能用几秒钟读懂的句子。更何况作为读者,一两句话没搞 懂,并不影响你理解整本书,但对译者来说,这就不一样了 其次,这是一本讲英语的人写给讲英语的人的书,所以同很多要照顾非英语读 者的技术文档不同,它在用词,句式方面非常随意。英语读者会很欣赏这 点,但是对外国读者来说,这就是负担了。 再有, Bruce eckel这样的大牛人,写了1000多页,如果都让你读懂,他岂不是 太没面子?所以,书里还有一些很有“禅意”的句子。比如那句著名的“The genesis of the computer revolution was in a machine. The genesis of our programming languages thus tends to look like that machine.”我就一直没吃准该怎 么翻译。我想大概没人能吃准,说不定 Bruce要的就是这个效果 这是一本公认的名著,作者在技术上的造诣无可挑剔。而作为译者,我的编程 能力差了很多。再加上上面讲的这些原因,使得我不得不格外的谨慎。当我重 读初稿的时候,我发现需要修改的地方实在太多了。因此,我不能现在就公开 全部译稿,我只能公开已经修改过的部分。不过这不是最终的版本,我还会继 续修订的。 本来,我准备到10月份,等我修改完前7章之后再公开。但是,我发现我又有 点要放弃了,因此我决定给自己一点压力,现在就公开。以后,我将修改完 章就公开一章,请关注www.wgqgh.com/shags/tii.html 如果你觉得好,请给告诉我,你的鼓励是我工作的动力;如果你觉得不好,那 就更应该告诉我了,我会参考你的意见作修改的。我希望能通过这种方法,译 出一本配得上原著的书。 2003年9月8日 第1页共34页

shhgs@wgqqh.com ￾ 1 ✁ ✂ 34 ✁ 1   2002 7    chinapub  !"# $%!&'( )*+, -.& /0(12 345( 67,893 :);8(?@ AB3CDE Bruce Eckel FG(HIJK (L(M NOPA!Q $$RS TTU3 1000 VW( XYZRS(@4[\]^_ `a b:c!Q,d(ef9 g 7 h ijk l,Dm(no4 cpqrst (u*vw$ xy1(U z{!,(|} ~/ 3 3 ce€‚ƒ„*…e†X‡(ƒ ˆ‚ƒ$‰Š‹(Œ Ž*…uc,>m‰‘i’ ˆ*…3Œ;ˆi•’=(Œ1™š 3eŒ›œ = žXŸ ¡¢£¤ ¥šQ$ X3¦, §¨ 3 ©‚ƒ(ª«¬©‚ƒ(ª( DE‡ŠV%­®¯‚ƒ š(°±…²X‡ AFˆ³ Œ´µ¶¯·¸¹‚ƒšºŠ»¼ 3 C ¥½¾šQ$ ¿À, Ám Bruce Eckel ¦(Âê «, 1000 VW ÄÅÆÇ¡= GÈX ɜ¶ÊDE Ëm3̊mÍ Î¹Ï(Œ8ÄYŒÐÑ(Í The genesis of the computer revolution was in a machine. The genesis of our programming languages thus tends to look like that machine.Ï3ҜÓÔwÕ Z|Â֜ª;ÓÔ $XO Bruce %( ×ØÅ 3 KÙ(ÑÐ 1šF°±J(ÚÛÜÝÞßà1™š (áâ ;ãB,ŠVÁäJJ¶©( Ìåæ ç‰X‰Xè½(éê  fë(M ìíî%ïð(rµñFÉV,æò X;íFK cë ó;Kôõïð^(X^ Xb:( ºö ÷ïø( Q Ôùg 10 ú -ïð 7 ûuÁK ìíüm C%kl, æòNO¬ýþ3Cã íFKE ïð3 ûK3û  www.wgqqh.com/shhgs/tij.html ÄÅ¡‰‘ ¬# ¡(ay1( ã ÄÅ¡‰X‘ Y vw#, º ¡(¹ 1ïð(7;^ †µ  !3 ‰JåÐ(  shhgs 2003 9  8 

1:对象简介 我们剖析事物的本质,从中形成概念,并根据需要赋予它重要性。这 切很大程度上是源于,我们所使用的语言已经在其形式中包含了一套为它 的使用者所完全接受的规范,而我们正属于接受这一规范的那群人.如果 我们拒不接受语言在数据的组织与分类方面的原则的话,那我们根本就没 法说话。” Benjamin Lee Whorf(1897-1941) 计算机革命的推动力在于机器。于是机器的发展也左右了编程语言发展。 然而真正被用作延伸智力的工具的计算机(就像 Steve jobs喜欢说的, “思想的自行车”)并不很多,它们更多的是被用来表达思想。所以结果 就是,它们看上去已经不那么像机器了,而更像我们思想的一部分。就像 文字,绘画,雕塑,动画以及电影一样,它已经成为一种新的媒体。而面 向对象的编程( object- oriented programming缩写是OOP)正是这 运动的一部分 本章会向你介绍OOP的基本概念和开发的方法。本章,以及本书都假设 你有过程语言的编程经验,虽然不一定是C的。如果你决定在继续本书之 前,要在编程和C的语法上作更为充分的准备,你可以去看看本书封底所 附的,名为 Foundations for Java的练习CD。 本章是一个背景介绍和补充材料。很多读者会觉得,在没理解大背景之前 就去编写面向对象的程序,会有点不舒服。因此这里会对很多概念做个介 绍,并且让你对OOP的概况有个清楚的了解。然而,有些人会认为在见 到具体的工作机制之前没必要了解整个大背景;这些人在还没有看到代码 之前就会被搞昏的。如果你属于后者,希望尽快进入这个语言的细节,没 关系,跳过这章就是了——跳过这章不会妨碍你写程序或者学语言。但是 最终你还是要回来补课的,因为只有这样你才会理解为什么对象很重要 而且该如何把它们用到设计中去 抽象的过程 所有的编程语言都提供抽象。甚至可以这么说,你能解决的问题的复杂程 度直接与抽象的种类与质量相关。我所说的“种类”是指,“你到底抽象 了些什么”。汇编语言是对计算机的抽象,随后许多所谓的“命令”语 (诸如 FORTRAN, BASIC和C)是对汇编语言的抽象。这些语言较汇编语 言有了巨大的进步,但这仍然是一种初级的抽象,仍然要求你从计算机的 角度,而不是从待解决的问题的角度来思考。程序员必须在机器模型(在 解决空间”,也就是你要对那个问题建模的地方,比如在计算机上)与 待解决的问题的模型(在“问题空间”,也就是有问题要解决的地方)之间 建立关联。处理这种映射所带来的压力,以及编程语言对此无能为力的现 第2页共34页

shhgs@wgqqh.com ￾ 2 ✁ ✂ 34 ✁ 2 1:  Í (  *ŽÖ žî%A% 3 ŠÂâzJ ) Dçˆ(ƒôõF§´*!",3#™A (爚Dc$%(&' à())$% 3&'(Y*ª...ÄÅ +X$%ƒF,(-.„/µ¶(å0(› Y œ $›Ï B en jam i n Lee Wh orf (1897-1941) 12345(6 ãF)37)37(ì8[9:,áâƒì8 ;à?@ã(yA(123 (} Steve Job s BC$( Í D|(ýEFÏ) žXŠV AV(=ˆQGHD|DEIÅ  AD$(Í †/ÏŒ Í ¡gh„V ,́Zύქ123(„V ¸ŽVD(Í 5Ïƒ (‘Ä FORTRAN , BASIC  C)¥áƒ(„V ̃’áƒ m,Â(t  •;3†f(„V •;%¡123( z àX™£N(‡ˆ(zQD âhšo›F37œ(F Í £Nž4Ï [¡%¥YׇˆŸœ(rµ 8ÄF123J)„ ™£N(‡ˆ(œ(FÍ ‡ˆž4Ï [m‡ˆ%£N(rµ)u4 Ÿ ¡¢¢ †£¤D¥Q(ã EPá⃥òÜ;™ã(í

实,造成了程序难写以及维护代价高昂的后果。此外它还带来一个副产 品,就是所谓的“编程方法”的行业。 取代对机器建模的另一个途径是对你要解决的问题建模。早期语言,诸如 LISP和APL选择了“以某种特殊的视角来观察世界”的方法(分别是 “归根到底,所有问题都是列表”或“所有问题都是算法”)。 PROLOG 则将所有问题都转换成一系列决策。用这类语言编程,成了在约束条件下 的编程,而编程也仅限于操控图像符号。(后来证明这种做法的局限性太 大了。)它们的设计是针对某些很特殊的问题的。对于那些问题,这些方 法都干得不错,但是一旦步出这一领域,它们就显得太滑稽了。 面向对象的方法则更进了一步,它为程序员提供了能在问题空间表述各种 元素的工具。这种表述是非常通用的,这样程序员就不会被限制在某类特 殊问题上了。我们将问题空间的元素同它在解决空间的表述称为“对 象”。(此外还需要一些在问题空间并无对照的对象。)这一思想的要点 是,通过往程序里面添加新的对象,可以让它适用于问题的各种变例。于 是当你阅读代码的时候,它也在向你讲述它要解决的问题。这比我们曾经 见过的语言抽象更为灵活也更为强大。2由此OOP允许你以问题的角 度,而不是以要解决问题的计算机的角度来描述问题。不过它与计算机还 是有联系:每个对象看上去都有点像计算机—一它有状态,有可以让你来 执行的操作。但看上去这种对真实世界的模拟还不算太糟——在真实世界 中对象也都有自己的特点和行为。 Alan Kay总结了 Smalltalk的五项基本特征。这是最早获得成功的面向 对象的编程语言,也是Java所依赖的基础之一。这些特征代表了纯的面 向对象的编程方法 1.万物皆对象。将对象想成一种特殊的变量;它存储数据,而且还可以让 你“提要求”,命令它进行某些操作。从理论上讲,你可以把所有待解 决的问题中的概念性组件(狗,建筑,服务等)都表示成程序里的对象。 2.程序就是一组相互之间传递消息,告诉对方该干些什么的对象。你只要 向那个对象“发一个消息”,就能向它提出要求。更确切的说,你可以 这样认为,消息是调用专属某个对象的方法的请求。 3.每个对象都利用别的对象来组建它自己的记忆。换言之,你通过将已有 的对象打成一个包,来创建新的对象。由此,你可以将程序的复杂性, 隐藏在对象的简单性之下。 4.对象都有类型。说这句话的意思是,任何对象都是某个类的实例 ( instance of a class),而这里的“类( class)”就是“类型type)”的意思。 用以区分类的最突出的特点就是“你能传给它什么消息?” 5.所有属于同一类型的对象能接受相同的消息。以后你就会知道,实际上 这是“定义”而不是特点。一个“ circle”型的对象也是一个“ shape”型 的对象,所以可以保证 circle能接受 shape的消息。也就是说,你写给 shape的代码能自动交由任何符合 shape描述的东西处理。这种互换性 ( substitutability)是OOP最强大的功能之 第3页共34页

shhgs@wgqqh.com ￾ 3 ✁ ✂ 34 ✁ 3 ñ ڎ,âhU«EP¦§p¨©ª(Åò½A¥Q3׫¬ 2 D(Í áâµÏ(En ­p¥37Ÿœ(®3ׯ°¥¡%£N(‡ˆŸœ±@ƒ ‘Ä LISP  AP L ²³,Í E´†µ¶(·Q¸¹º»Ï(µ(¼ Í ½gh Dm‡ˆÆ¾GÏ|Í Dm‡ˆÆ2Ï)PROLOG 0Dm‡ˆÆ¿ÀŽ3w¾NÁˆ /ƒá⠎,FÂÃÄÅÆ (áâ àáâ[ÇÈ)ÉÊË}ÌÍ(QÎÏ †T(ÐÈÉ Â,)A([1Ñ¥´ÌŠµ¶(‡ˆ(¥)Ẏˆ ̵ Æ҉XÓ 3Ô! 3ÕÖ A׉ÉØÙ, ¶U¥V(µ0t,3 A™âhš‚ƒ,;F‡ˆž4Gچ ÛÜ(yA †G¯·ˆ( ¦âhšXº=ÈnF´/µ ¶‡ˆJ,‡ˆž4(Û܇AF£Nž4(GÝ™Í ¥ VÏ(ò½î%3ÌF‡ˆž4žÜ¥­(¥V) 3D|(%C  ^Þâh˶ßäR(¥V ÝEÇAàˆ)‡ˆ(چáâ)  ¡ãp€(M A[FU¡©A%£N(‡ˆ 8\õ ^(ƒ„V™äå[™æ ✄ ☎ ✆ çò OOP 莡E‡ˆ( z àXE%£N‡ˆ(123(zQ釈X^A„123 m¡w :ê×¥V<JJÆmC}123yyAmëì mÝEÇ¡Q íE(É1<JJ †¥<ñº»(œîX2ÉïyyF<ñº» *¥V[Æmýþ(µCE™ Al a n Ka y ðI, Sm a l lta l k (ñxY µò b±ó‰Žô(¶U ¥V(á⃠[ Ja va Dõö(Y÷u3 ̵òpG,ø(¶ U¥V(áâµ: 1. ¥V|Ž3†µ¶(ዠAùú, àkÝEÇ ¡Í ‚%Ï 5AtE´ÌÉ1¢ûJ© ¡ÝEPDm™£ N(‡ˆ*(Ö-Å(ü Ÿý jþ-)ÆGŽâhË(¥V 2.   ¡ó% UY×¥VÍ ì3×Ï ;UA‚!%($ ¡ÝE ¦Ù™ ˆ)´×¥V(µ( 3.  !"#$% &'( )*+Àu ¡^ôm (¥V]Ž3×! QŸR(¥Vçò ¡ÝEâh(‰Š  F¥V( uÆ 4. !,-.$ Œ›(¹D ¥VÆ´×/(ñâ (instance of a class) à Ë(Í /(class)ÏÍ /(type)Ï(¹D ˆE /(b!(µCÍ ¡;¬AZÊÏ 5. /,012 -.345 2E¡º ñJ Í OÏàXµC3×Í circleϝ(¥V[3×Í shapeϝ (¥V DEÝEÎ circle ;$% shape ([$ ¡«¬ shape (p€;ý ç Ì shape é(¢¢ †À (substitutability) OOP bæÂ(ô;u3

Booch还给对象下了个更为简洁的定义 对象有状态,行为和标识。 这就是说,对象可以有内部数据(这给了它状态),有方法(因而产生了行 为),以及每个对象都能同其它对象区分开来——具体而言,每个对象在 内存里都有唯一的地址。3 对象有接口 或许亚里士多德是第一个认真研究类型(type)这个概念的人;他提到过 “鱼类和鸟类”这种概念。对象,虽然都是独一无二的,但同时也是某种 有着相同特征和行为的对象的类的一员。这个概念直接以 class关键词 的形式为Smua-67—第一种面向对象的语言所采纳。而 class也为 程序引入了一种全新的类型。 Simula,就像它的名字所说的,是为了开发诸如经典的“银行出纳问 题”而创建的。在这个问题中,你有很多出纳员、客户、帐户、交易以及 钱——总之,很多“对象”。那些除了程序执行时状态会有所不同,其它 都完全相同的对象,会被集中起来,统称为“对象的类( classes of objects)”。由此得出了 class关键词。在面向对象的编程中,创建抽 象的数据类型( class)是一项基本概念。抽象数据类型的工作方式同内置 数据类型的几乎没什么不同:你可以创建这个类型的变量(在OOP的术语 中,这被称为对象 object或实例 instance),然后操纵这些变量(称为送 消息 sending messages或请求 request,你传给对象一个消息,由它 来决定该作些什么。)每个类的每个成员(元素 element都有某些共性: 每个帐户都有余额,某个出纳都能受理存款,等等。同时,每个成员还都 有自己的状态。每个帐户的余额是不一样的,每个出纳都有自己的名字等 等。因此,出纳、客户、帐户、交易等等,它们每个都在计算机程序中代 表一个唯一的实体。这个实体便是对象,而每个对象都属于某个类,而这 个类会定义它的特征与行为。 因此,虽然面向对象的编程就是创建一些新的数据类型,但几乎所有的 OOP语言都选择“cass”这个关键词。所以,当你看到“type”的时 候,应该想到它就是“ class”,反之亦然 由于类描述的是一组具有相同特征(数据元素)和行为(功能)的对象,所以 类实际上是一种数据类型。因为,就拿浮点数举例,它也有它自己的特征 和行为。类同数据类型的区别在于,类是程序员为解决特定问题而定做 的,而数据类型是为了表示机器的存储单元而设计的,它是现成的,是程 序员无可奈何时的选择。你可以根据需要添加新的数据类型,并以此来扩 充编程语言。编程系统欢迎这些新的类,它会在管理和类型检査方面给予 这些类与内置类完全相同的待遇。 第4页共34页

shhgs@wgqqh.com ￾ 4 ✁ ✂ 34 ✁ 4 B ooch ¬¥VÆ,י (O: ¥Vmëì E™ $ ¥VÝEm,( ¬,Aëì) mµ(æà¬0,E ™) EPê×¥VÆ;‡§A¥V QyyATà ê×¥VF ùËÆm3(r ✄ ✝ ✆  |Ž Ë!V"3×هµòE™(¥V(/(3š ×ÖÒ$E class (³ (´™ Si m u l a -67yy3†¶U¥V(ƒD)*à class [™ âh+t,3†cR(/ Si m u l a }A(ÑKD$( ™,ì‘Äõ,(Í -E!*‡ ˆÏàŸ(F ׇˆ* ¡mŠV!*š. /0. 10. SEP 2yyðu ŠVÍ ¥VÏYÌ3,âhíEëìºmDX‡ §A Æc>‡(¥V º=4*9Q 5Ý™Í ¥V(/(cl a sses of ob jects)Ïçò‰!, class (³F¶U¥V(áâ* Ÿ„ V(,/(cl a ss)3xY Ö„V,/(y1µ´‡6 ,/(ijœZX‡7¡ÝEŸ ×/(á‹(F OOP (±ƒ * =ݙ¥V object |ñâ instance) ;É8 Ìá‹(ݙ9 sending messages | request ¡¬¥V3× çA QNOw1́Z)ê×/(ê׎š (ÛÜ el em en t)Æm´Ì:7 ê×10Æmo; ´×!*Æ;%¢ùu?; ✄✞ ✆ ç)/é(3-Am>‡µò(,ÛÜ)E™(ô; )(¥V DE /ñJ3†,/æ™ @AC,Bâ A[mAýþ(µò E™/‡,/( ¼F) /âhš™£NµO‡ˆàOT ( à,/™,G37(ùú Ûà[1( AíŽ( â hšÜÝC(²³¡ÝEî%ßäR(,/ žEòQD ^áâƒáâw5CE ÌR(/ AºFF¢/GHµ¶¬ Ì/„6/c>‡(™I

面向对象的方法并不限于创建模拟场景。不论你承认与否,任何程序都在 模拟你所设计的系统。用了OP技术,你就能很容易地将一大堆问题简 化成一个简单的解决方案。 旦创建了类,你就能创建任意多的那个类的对象,然后把它们当作待解 决的问题中的元素来进行操控。实际上,面向对象的编程的挑战之一就 是,如何在问题空间的元素与解决空间的对象之间建立一种一对一的映 射 但是怎样让那些对象来为你干活呢?必需要有办法向对象发请求,这样它 才能工作。比如完成一次交易,在屏幕上画些东西或者按一下开关之类 的。而且每个对象只能满足某些请求。你能向对象发送的请求是由其接口 ( interface)所定义的,而决定接口的则是对象的类型。可以用电灯泡来 作一个简单的例子 Type Name Interfa bri gh tend di mo Light lt new Light () 1t.on(); 接口只管你能向这个对象发什么请求。还必须要有能满足这一请求的代 码。而这些代码,以及隐藏着的数据,组成了实现(imp/ ementation) 从过程编程的角度来讲,事情没那么复杂。类中的方法都是与各种请求相 关联的,因此当你向这个对象提出请求的时候,就会调用这个方法。这个 过程通常被称为,你向一个对象“传了一个消息(提了个请求)”,而这个 对象会决定该如何处置这个消息(执行代码)。 这里,这个类型/类的名字是 Light,而这个具体的 Light对象的名字是 t。你向 Light对象提出的请求有开灯,关灯,让它更亮一点或是暗点。 通过定义 Light类型的“ reference”(It),和用new请求一个新对 象,你创建了一个 Light对象。发送消息的时候,你要用点号 (dot/ period)将对象的名字和那个消息连起来。如果编程的时候用到的都 是已有的类,那么这点知识已经够用了 上面的图表遵循了 Unified Modeling Language(UML)的格式。每个类 都由一个方框来表示,这个类的名字写在方框的顶部,中间是你要关心的 第5页共34页

shhgs@wgqqh.com ￾ 5 ✁ ✂ 34 ✁ 5 ¶U¥V(µžXÈ)ŸœîJdXû¡KلL âhÆF œî¡D[1(w5ˆ, OOP °± ¡;ŠRSr3ÂM‡ˆ NŽ3× (£NµO 3ÔŸ,/ ¡;Ÿ ¹V(Y×/(¥V ;PA 1™£ N(‡ˆ*(ÛÜQtEÉÊñJ ¶U¥V(áâ(ÞPu3  ÄF‡ˆž4(Û܄£Nž4(¥Vu4Ÿ 3†3¥3(£ ¤ Õ¦ÇYÌ¥VQ™¡ÒåQÊoî%mRU¥Vì ¦A €;y18ÄŽ3¨S FSTJMÌ|šU3Æu/ (àkê×¥Vó;VW´Ì¡;U¥Vì9(ç§$X (interface)DO( àNO$X(0¥V(/ÝEˆQYZQ 13× (â7 Light lt = new Light(); lt.on(); $XóF¡;U ×¥VìZo›%m;VW 3(p €à Ìp€ EP .(, -Ž,ñí(implementation) ^âáâ(zQ© [œYZ‰Š/*(µÆ„Ú†> ¡( æò ¡U ×¥V‚!(M ºˆ ×µ × ^â·=ݙ ¡U3×¥VÍ ,3×(‚,×)Ï à × ¥VºNOwÄ¢6 ×(íEp€) Ë ×///(ÑK Li gh t à ×AT( Li gh t ¥V(ÑK lt¡U Li gh t ¥V‚!(mY Y ÇA\3C|]C ^O Li gh t /(Í referen ceÏ(lt) ˆ n ew 3×R¥ V ¡Ÿ,3× Li gh t ¥Vì9(M ¡%ˆCÍ (d ot/p eri od )¥V(ÑKY×^9QÄÅáâ(Mˆg(Æ ôm(/ YZ Côõ_ˆ, J¶(ËG`a, Unified Modeling Language(U M L)(è´ê×/ Æç3×µbQG ×/(ÑK«Fµb(c *4¡%q(

数据元素,而方法( method,指属于这个对象的函数。它接受你传给这 个对象的消息)则列在方框的底部。通常UML的设计图只会显示类的名字 以及 public方法,所以中间部分是不显示的。如果你只对类的名字感兴 趣,那么最下面的那部分也可以不显示。 对象会提供服务 当你开发一个程序或者分析一个程序的设计时,理解对象的最佳的方式是 把它们当作“服务的提供者”。程序本身会为用户提供服务,而它通过使 用其它对象所提供的服务来完成这个工作。你的任务是制作(或者在更理 想的情况下,从现有的代码厍中找出)一组能为解决问题提供最佳服务的 对象 这么做的第一步是问“如果我可以像变魔术那样把东西从帽子里拿出来, 我该拿出些什么东西,哪些对象能立即帮我解决问题?”举例来说,假设 你要创建一个簿记程序。可能你会想应该有一些保存预设的输入界面的对 象,一组进行簿记计算的对象,以及一个能在各种打印机上打印支票和发 票的对象。有些对象或许已经有了,但是那些还没有的应该是什么样的 呢?它们应该提供哪种服务,还有它们要完成任务的话,又该用哪些对象 呢?如果你不断分析下去,最终你会发现,不是“那个对象写起来很容 易”就是“那个对象已经有了。”这是将问题分解成一组对象的一个合理 的方法 将对象视作服务的提供者还有一个额外的优点:能提高对象的内聚性 ( cohesion)。内聚性高是高质量的软件设计一个基本要求:就是说软件 的各种组件(比如对象,也可以是方法或类库)应该能很好的“组装在 起”。设计对象时常犯的一个错误就是,往对象里塞了太多的功能。举例 来说,设计支票打印模块的时候,你也许会决定设计一个能通晓所有排格 式和打印工作细节的对象。很快你就会发现这个任务太艰巨了,或许应该 用三个或是更多对象来完成这个工作。第一个对象应该是支票格式的目录 册,通过査询这个目录册可以获得该如何打印支票的信息。第二个对象, 或是一组对象,应该是能分辨各种打印机的通用的打印接口(但是对簿 记,它一窍不通——这个模块应该买来而不是自己写)。以及使用上述两 个对象所提供的服务的,能最终完成任务的第三个对象。由此每个对象都 提供一组互补的功能。在一个良好的面向对象的设计中,每个对象都应该 只作一件事,并且作好一件事,而不是去作太多的事情。就像这里看到 的,这样不仅能发现哪些对象应该买(打印机接口对象),而且能设计出今 后能复用的对象(支票格式的目录册) 将对象视作服务的提供者还是一种很了不起的简化工具。它不仅在设计过 程中有用,而且还能帮助别人理解你的代码或者复用这个对象——如果他 们认同这个对象所提供的服务的话。将对象视作服务的提供者能使对象更 容易地被用于设计。 第6页共34页

shhgs@wgqqh.com ￾ 6 ✁ ✂ 34 ✁ 6 ,ÛÜ àµ(method Œ)) ×¥V(d,A$%¡¬ ×¥V()0¾Fµb(h· U M L ([1Ëóº×/(ÑK EP p u b l i c µ DE*4X×(ÄÅ¡ó¥/(ÑKef g YZbƶ(Y[ÝEX×   ¡ì3×âh|š3×âh([1 ¢£¥V(bh(µ´ PA 1Í jþ(‚ƒšÏâh pº™ˆ0‚ƒjþ àA^ç ˆ§A¥VD‚ƒ(jþQŽ ×y1¡( þn1(|šF¢ |([Æ ím(p€i*j! )3-;™£N‡ˆ‚ƒbhjþ( ¥V ZT(3‡Í ÄÅÝE}ák±Y¦PlË@!Q w@!́Z mÌ¥V; no£N‡ˆÊÏBâQ$ Z[ ¡%Ÿ3×pqâhÝ;¡º|vwm3Ìù?[(rt»¶(¥ V 3-tEpq12(¥V EP3×;Fچ]s3J]stuì u(¥VmÌ¥V|Žôõm, YÌœm(vwZ¦( QÊAvw‚ƒm†jþ mA%Ž þ(› üwˆmÌ¥V QÊÄÅ¡XvÆJ b:¡ºìí XÍ Y×¥V«9QŠR SÏÍ Y×¥Vôõm,Ï ‡ˆ£Ž3-¥V(3×¢ (µ ¥V·1jþ(‚ƒšm3×;½(wC7;‚©¥V(x (coh esi on )x©©‹(yÅ[13×Y %7$yÅ (چ-Å(8Ä¥V [ÝEµ|/i)vw;Š‘(Í -zF3 9Ï[1¥V·{(3×Ó| Þ¥VË},ÉV(ô;Bâ Q$ [1tu]sœ~(M ¡[ŽºNO[13×;Dm€è ´]sy1uv(¥VŠs¡ºìí × þɁ, |Žvw ˆL×|V¥VQŽ ×y13×¥Vvwtuè´(‚ƒ „ ^H… ׂƒ„ÝEó‰wÄ]stu(†×¥V |3-¥V vw;‡Ú†]s3(ˆ(]s$X (¥p q A3ˆXyy ל~vw5QàXýþ« )EPçˆJe ×¥VD‚ƒ(jþ( ;b:Ž þ(L×¥Vçòê×¥VÆ ‚ƒ3-e(ô;F3׉‘(¶U¥V([1* ê×¥VÆvw ó13Ł žk1‘3Ł àXJ1ÉV([} Ë<g ( ¦XÇ;ìímÌ¥Vvw5 (]s3$X¥V) àk;[1!d ;‰ˆ(¥V(tuè´(‚ƒ„) ¥V·1jþ(‚ƒš3†Š,X9( NyAAXÇF[1^ â*mˆ àk;oŠ¼ª¢£¡(p€|š‰ˆ ×¥VyyÄÅG ه ×¥VD‚ƒ(jþ(›¥V·1jþ(‚ƒš;ç¥V RSr=ˆ)[1

隐藏实现 将程序员分成类的创建者(c| ass creator那些创建新的数据类型的人)和 客户程序员( client programmer那些使用这些类编程的人)能帮助我 们更好地理解这个问题。客户程序员的目的是收集各种类,以便能快速开 发应用程序。而类的创建者的目的是创建一些这样的类,它们只透露一些 客户程序员必须知道的东西,其它部分则被完全隐藏了。为什么?因为隐 藏之后,客户程序员就不能访问了,也就是说类的创建者们可以根据需要 修改隐藏部分而不用担心会对其他人造成影响。通常隐藏起来的都是这个 类最脆弱的,很容易被粗心大意或不知情的客户程序员给弄坏的内脏部 分,所以把实现隐藏起来能减少程序的bug 隐藏实现,这一概念的重要性无论如何强调都不会过分。无论是那种关 系,有一个为各方都尊重的边界是非常重要的。创建一个类库之后,你就 与客户程序员建立了某种关系。他们也是程序员,他们用你的类库来组装 一个应用程序,也可能是一个更大的类库。如果所有人都能看到类的所有 成员,那么客户程序员就能对这个类作任何事,因此也谈不上什么强制性 的规则了。尽管你真的不想让客户程序员直接操控类中的某些成员,但是 如果没有访问控制的话,你也没办法禁止他去这么做。这个类只能赤裸裸 地面对整个世界。 所以要控制访问权限的首要原因就是,禁止那些客户程序员去碰他们不该 动的东西——就是那些数据类型内部运作所必须的东西。只允许他们接触 解决问题所必需的接口。实际上这也是提供给用户的一种服务,因为由此 他们能很方便的看出哪些东西对他们很重要,哪些跟他们没关系 第二个原因是允许类库设计人员能在不打搅客户程序员的情况下修改类的 内部工作方式。比如,刚开始设计这个类的时候时,为了降低开发难度, 你用了一种很简单的方法,但随后你发觉应该重写这段代码,让跑得快 些。如果这个类的接口与实现分得很清楚,并且保护得很好,那么做起来 就会很方便。 Java用了三个明确的关键词来设置类中的边界: public, private,和 protected。它们的用法和意思都相当明了。这些访问控制符表示谁能使 用由它定义的东西。 public表示后面跟着的东西谁都能用。而 private 关键词则表示,除非是类的创建者用这个类的方法进行访问,否则没人能 访问到这个元素。 private是竖在你与客户程序员之间的一堵墙。那些要 访问 private成员的人,会在编译的时候得到一个错误。 protected关键 词很像 private,它们的区别在于,继承类能够访问 protected成员,但 是不能访问 private成员。继承问题过一会再介绍 Java还有个“缺省”的访问权限,如果你没用上面三个的话,那就是指 它了。通常把它称为 package访问权限。因为同属这个 package的类 第7页共34页

shhgs@wgqqh.com ￾ 7 ✁ ✂ 34 ✁ 7  âhšŽ/(Ÿš(class creator YÌŸR(,/(ª)  /0âhš ✄ ✟ ✆ (client programmer YÌçˆ Ì/áâ(ª);oŠ ‘r¢£ ׇˆ/0âhš(‚(‹4چ/ E=;sŒ ìvˆâhà/(Ÿš(‚(Ÿ3Ì ¦(/ AóŽ3Ì /0âhšo›( §A0=c ,™ZÊæ™ u /0âhšX;‡, [$/(ŸšÝEî% ïð àXˆÀqº¥§GªÚŽŸ · 9Q(Æ × /b‘( ŠRS=’q¹|X[(/0âhš¬(•  DEPñí 9Q;âh( b u g   ñí 3Ö(%ÜûÄæÆXº^ÜûY† w m3יڵÆ(™»¯·%(Ÿ3×/iu ¡ „/0âhšŸ ,´†wG[âhš Gˆ¡(/iQ-z 3×vˆâh [Ý;3×Â(/iÄÅDmªÆ; Ï, ̏‡ÊnÌG¨;ç ˆçAO(p u b l i c G¶¡.(¨Æ;ˆà p ri va te (³0G 3¯/(Ÿšˆ ×/(µtE‡ L0œª; ‡g ×ÛÜp ri va te ©F¡„/0âhšu4(3ª«YÌ% ‡ p ri va te Žš(ª ºFá(M‰g3×Ó|p rotected ( ³Š} p ri va te A( ¼F) öK/;_‡ p rotected Žš  X;‡ p ri va te ŽšöK‡ˆ^3ºÁ Ja va m×Í ¬­Ï(‡žÈ ÄÅ¡œˆJ¶L×(› YŒ A,·PAݙ p a cka g e ‡žÈ晇) × p a cka g e (/

可以访问这个 package中其它类的“缺省权限”的成员,但是出了这个 package,它们就都是 private的了。 复用实现 类创建完成并且测试通过之后,它就应该能(很好地)表示一段有用的 代码。但实际上代码复用并不像我们希望的那样容易;要设计一个复用性 良好的对象,需要经验和远见。代码复用是OOP语言最显著的优点之 复用代码最简单的方式是直接用这个类来创建对象,但是你也可以将那个 类的对象放到一个新的类中。我们把它称为“创建一个成员对象”。为了 能让那个新的类提供你所设计的功能,它可以由任意多个,任意类型的对 象,以任意形式组合在一起。由于你是用已有的类来合成新的类,因此这 一概念被称为合成( composition,如果这个对象是动态合成的,通常把 它称为聚合 aggregation)。通常将合成称为“有(has-a)”关系,就像 轿车有引擎 C Engine (这个讲解轿车的UML关系图,用实心菱形表示合成关系。通常如果要 让我表示这个关系的话会更简单:就是一根直线,没有菱形。l) 合成具有极大的灵活性。新类里面的成员对象通常都是 private的,因此 使用这些类的客户程序员们是无法访问这些对象的。这点能让你在不影响 已有的客户代码的前提下,修改这些类。你还可以在运行时修改这些成员 对象,并以此动态地改变程序地运行。下面要讲的继承就没有这种灵活 性,如果你用继承创建一个类,编译器肯定会加上某些编译时的限制的 由于继承在OoP中是如此重要,因此会被反复强调,以至于新手们会认 为,应该尽量使用继承。其实一味的使用继承会导致很奇怪也很复杂的设 计。相反,在创建新类的时候,你应该优先考虑使用合成,这么做会更简 单也更灵活。如果这么做的话,整个设计也会变得更加井井有条。等你有 了一点经验之后,你就会自然而然的知道继承应该用在哪里了 继承:复用接口 对象这个概念本身就是一件很有力的工具。它能让你依照概念把数据与功 能结合在一起,这样你就不用站在运行程序的计算机的角度上,而是站在 解决问题的角度上来写代码了。这个概念作为程序的基本单位,在编程语 言中用 class这个关键词表示。 第8页共34页

shhgs@wgqqh.com ￾ 8 ✁ ✂ 34 ✁ 8 ÝE‡ × p a cka g e *§A/(Í ¬­žÈÏ(Žš !, × p a cka g e AÆ p ri va te (,  3Ô/ŸŽžk®¯^u Avw; (Š‘r)G3¦mˆ( p€ñJp€‰ˆžX}7(Y¦RS %[13׉ˆ ‰‘(¥V î%õ\° p€‰ˆ OOP ƒb×Ð(wCu 3 ‰ˆp€b (µ´Ò$ˆ ×/QŸ¥V ¡[ÝEY× /(¥Vkg3×R(/*PAÝ™Í Ÿ3׎š¥VÏ™, ;ÇY×R(/‚ƒ¡D[1(ô; AÝEç ¹V× ¹/(¥ V E ¹´-F39ç)¡ˆôm(/QŽR(/ æò 3Ö=ݙŽ(composition ÄÅ ×¥V ìŽ( ·P Aݙx aggregation)·ŽÝ™Í m(h a s-a )Ïw } Í ±Fm+²Ï ( ש£±F( U M L wË ˆñq³GŽw·ÄÅ% ÇG ×w(›º 73Ò´ œm³ ✄ ✠ ✆ ) ŽAmµÂ(äåR/˶(Žš¥V·Æ p ri va te ( æò çˆ Ì/(/0âhšÜ‡ Ì¥V( C;Ç¡FXŸ  ôm(/0p€(‚Æ ïð Ì/¡ÝEFXEïð ̎š ¥V žEò ìrðáâhrXEƶ%©(öKœm †äå  ÄÅ¡ˆöKŸ3×/ á7¶OºäJ´Ìá(Èn( ç)öKF OOP *Äò% æòº=>‰æ E†)R·ºÙ ™ vwr‹çˆöK§ñ3¸(çˆöKº¹ºŠ»¼[Š‰Š([ 1>> FŸR/(M ¡vww/ ½çˆŽ ZTº [äåÄÅ ZT(› ¤×[1[ºá‰ä¾¾mÄ-¡m ,3Cõ\u ¡ºý;à;(öKvwˆFmË,   ¥V ×Ö p3Ŋmã(yAA;Ç¡õ­ÖP,„ô ;IF39 ¦¡XˆIFXEâh(123(zJ àIF £N‡ˆ(zJQ«p€, ×Ö1™âh(Y ¿ Fá⃠*ˆ class ×(³G

然而,要是我们费尽心机编写了一个类之后,又不得不再写去一个功能类 似的全新的类的话,那就很惨了。要是能将已有的类克隆一份,然后在克 隆的类上修修补补,那就好了。而这正是继承( inheritance)的功效。只 是区别在于,如果原先那个类(称为基类 base class,父类 parent cass和超类 superclass)作过了修改,那么这个“克隆”(称为衍生 类,派生类 derived class或者继承类 in herited class或者子类 subclass, child class)也会随之发生变化。 Base Derived (在UML关系图中,箭头从派生类指向基类。你会发现,通常会有不止 个派生类。) 类不仅仅在描述一组施加在对象之上的限制;它还会同其它类发生关系。 两个类可以有一些共通的特征和行为,可能其中有一个比另一个特征更 多,能处理的消息也更多(或者处理的方式不同)。通过基类和派生类的概 念,继承表达了这种相似性。基类保存的是所有继承自它的类的共有特征 和行为。创建基类是为了表达,你对系统中某些对象的核心思想的理解 而衍生类则是从基类派生出来的,它所表达的是各种实现这个核心思想的 方式。 举例来说,有一个对垃圾分类的垃圾回收机。基类是“垃圾( trash)”, 每件垃圾都有重量,价值等等,而且可以切碎,融化或者分解。由它派生 出的一些具体的垃圾品种会有一些额外的特征(瓶子有颜色)或是行为( 罐可以压缩,铁罐可以磁化)。此外有些行为会不同(纸张的价值由它的品 种和状况决定)。通过继承,你能用类构建一个表述你要解决的这个问题 的类系( type hierarchy)。 第二个例子是经典的“ shape”案例。或许它能用于计算机辅助设计系统 或是用来模拟游戏场景。基类是“ shape”,每种形状都有大小,颜色, 位置等属性。从它那里继承下来的具体的形状——圆,矩形,三角形等- —都有额外的特征和行为。比如某些形状可以翻转。有些行为会不同,比 如计算面积的方法。整个类系体现了各种形状之间的相同和不同点。 第9页共34页

shhgs@wgqqh.com ￾ 9 ✁ ✂ 34 ✁ 9 ;à %Àrq3á«,3×/u üX‰XÁ«J3×ô;/ Á(cR(/(› YŠÂ,%;ôm(/ÃÄ3ú ;Fà Ä(/Jïïee Y‘,à (öK(inheritance)(ôØó  ¼F) ÄÅå/Y×/(ݙY/ base class Å/ parent class {/ superclass)1^,ïð YZ ×Í ÃÄÏ(ݙÆ0 / Ç0/ derived class |šöK/ inherited class |š/ subclass, child class)[º¸uì0áN (F U M L wË* ÈÉÇ0/ŒUY/¡ºìí ·ºmX+ 3×Ç0/) /XÇÇFé3-ÊäF¥VuJ(Èn Aº‡§A/ì0w e×/ÝEm3Ì:(µòE™ Ý;§*m3×8®3×µò V ;¢¢([V (|š¢¢(µ´X‡)^Y/Ç0/(Ö  öKGH, †>ÁY/ù(DmöKýA(/(:mµò E™ŸY/™,GH ¡¥w5*´Ì¥V(ËqD|(¢£ àÆ0/0Y/Ç0!Q( ADGH(چñí ×ËqD|( µ´ BâQ$ m3×¥ÌÍ/(ÌÍ~‹3Y/Í ÌÍ(tra sh )Ï êÅÌÍÆm‹ ¨Î-- àkÝEÏ ÐN|š£çAÇ0 !(3ÌAT(ÌÍ2†ºm3Ì;½(µò(эmÒÓ)|E™(Ô ÕÝEW ÖÕÝE×N)ò½mÌE™ºX‡(ØÙ(¨ÎçA(2 †ëNO )^öK ¡;ˆ/ڟ3×G¡%£N( ׇˆ (/w (typ e h i era rch y) ×âõ,(Í sh a p eÏOâ|ŽA;ˆ)123ۊ[1w5 |ˆQœîÜÝJdY/Í sh a p eÏ ê†ëÆmÂÞ ÒÓ ¿6-)AYËöKÆQ(AT(ëyyß à L-y yÆm;½(µòE™8Ä´ÌëÝE¿mÌE™ºX‡ 8 Ä12¶á(µ¤×/wTí,چëu4(>‡X‡C

Shape draw erase() moveD getcoloro setcol oro Circle Square Triangle 将描述问题之用的术语用于解决问题也是大有裨益的,因为这样你就不再 需要那些在讲述问题和解决方案之间的中间模型了。对于对象,类层次结 构是最主要的模型,由此你从用文字描述真实世界中的系统进到了用代码 描述这个系统。实际上,大家在用OOP设计时会遇到的难题之一是,它 从头到尾太简单了。习惯于用复杂方法解决问题的人可能会一开始就被这 种简单给难住了。 当你继承了一个类时,你也创建了一个新的类。这个新的类不仅包含了已 有类的所有成员(尽管 private成员已经隐藏起来了,是不能访问的), 更重要的是它复制了基类的接口。于是所有能够传给基类的消息也都可以 传给派生类。由于我们根据能它能接受什么消息来判断这是什么类,因此 这就意味着派生类“和基类是属于同一类型的”。在上面的例子里,“圆 也是一种形状”。这种由继承而产生的类的相等性是一扇能让你理解 OoP意义的门。 既然基类和派生类具有相同的基本接口,那么这个接口的背后就必须跟着 实现。也就是当对象收到某个消息的时候,它必须能执行一些代码。如果 你只是继承了一个类,其他什么都不做,那么基类里的方法会直接带进派 生类。也就是说派生类的对象不但与基类的对象的类型相同而且行为也 样。这可没什么吸引力 你有两种办法来区分新的派生出来的类和那个原来的基类。第一种方法很 简单:直接往派生类里加新的方法。这些新的方法不属于基类的接口。也 就是说由于基类不能完成所有的工作,你必须加上更多方法。这种简单原 始的继承方法常常是解决问题的完美方案。然而你还得仔细看看基类是不 是也需要这些方法。对于OoP的设计,这种反复发现的过程是很常见 的 第10页共34页

shhgs@wgqqh.com ￾ 10 ✁ ✂ 34 ✁ 10 釈uˆ(±ƒˆ)£N‡ˆ[Âmâã( æ™ ¦¡XÁ î%YÌF©‡ˆ£NµOu4(*4œ,¥)¥V /ä¨I Úbå%(œ çò¡ˆ…Ké-3ë;Ç¡¢£ OOP ¹(ì í;Y/Ç0/Am>‡(Y $X YZ ×$X(co›¡. ñí[ ¥V‹g´×(M Ao›;íE3Ìp€ÄÅ ¡óöK,3×/ §GZÆXT YZY/Ë(µºÒ$¥tÇ 0/[$Ç0/(¥VX„Y/(¥V(/>‡àkE™[3 ¦ ݜZî+ã ¡me†RQ R(Ç0!Q(/Y×åQ(Y/3†µŠ 7Ò$ÞÇ0/ËäR(µ ÌR(µX))Y/($X[ $ç)Y/X;ŽDm(y1 ¡o›äJVµ † å (öKµ··£N‡ˆ(ïµO;ࡉðu‰ìí(^⊷ (

点击下载完整版文档(PDF)VIP每日下载上限内不扣除下载券和下载次数;
按次数下载不扣除下载券;
24小时内重复下载只扣除一次;
顺序:VIP每日次数-->可用次数-->下载券;
共34页,可试读12页,点击继续阅读 ↓↓
相关文档

关于我们|帮助中心|下载说明|相关软件|意见反馈|联系我们

Copyright © 2008-现在 cucdc.com 高等教育资讯网 版权所有