《UML面向对象设计基础》—第1章1.12节答案

1.12 答案
UML面向对象设计基础
①(a) 有两个建议:一是假设START方块完全被墙包围,二是假设某人在方格中忘记标记FINISH方块。修改算法处理这两种情况以及其他任何你考虑到的异常情况,如没有对advanceOK是否为真安全检查。

(b)该操作中的问题是:Grid对象中的insertHominoid操作需要location:Square (Hominoid对象的开始位置)的信息吗? 应该使用该信息告诉Homoid对象它的初始位置,但Homoid没有定义setLocation操作!因此,不应在Grid中定义insertHominoid操作,而应在Homoid中定义insertIntoGrid(grid:Grid,location:Square,out insetOK:Boolean)操作。此外,还需要在Grid中定义isAWallLocation:Boolean操作。

② 回答是肯定的。对象有一个不必声明的变量(实际上是常量),保存自己的句柄。该变量由关键字self,this,this 或Current(分别对应Smalltalk,C++,Java或Eiffel)来命名。

③ 因为这样做会使消息的目标改变了其中一个参数的句柄,这是一种拙劣的设计方法。消息的发送者有权保证其变量的句柄在发送消息的前后保持一致。少数语言禁止这种方法;在其手册中有这样的说明:“参数通过传送值进行对象访问,且不能被目标操作代码改变。”

④ 在彻底的面向对象语言如Smalltalk中,所有一切的都是对象;实际上,Smalltalk坚决地进行“不含数据”的定位。例如,在Smalltalk中下面的加法表达式

x <- 5 + 7
  解释为“向参数对象5和对象7发送消息plus。”赋值操作符(<-)解释为“用变量x替换对象12的句柄。”然而并不是所有面向对象语言都像Smalltalk那样严格。在类似Eiffel的语言中,仍然有数据类型(如integer,real,char,Boolean等)。但任何主要的结构在运行时是创建对象实例而不是数据实例的类。由于编程原因,Eiffel妥协了“所有都是对象”的原则:将整数、字符等作为可以与C代码接口兼容的数据类型。在C++中,具有标准数据类型的标准C程序可以与C++程序混合使用。因此,在C++中所有顾虑可以打消!但当我告诉人们纯面向对象中没有数据时,经常受到人们的抨击。最普通的例子是人们用Integer和Date反对我。为什么这些是类而不是传统的数据类型?在使用数字5之前,是否必须先声明Integer.New,而在使用1066年9月25日之前,是否必须先声明Date.New ?回答是否定的。诸如Integer或Date这样的类被称为文字类(literal classes)。属于文字类的对象称为文字对象(literal objects)。文字对象就是其表示的值。大多数文字对象是不变的:从不改变值。尽管每种面向对象语言都有其处理文字类的方式,但多数语言假设文字类的所有实例是预先定义的(或在原处通过转换类似“3月15日”的文本串创建的)。在将这种“类”作为标准数据类型的语言中,实例实际上是传统的数据值而不是对象。在下面两种情况下,从文字类进行实例化是不必要的也是非法的:

 `javascript
Integer.New;    // 非法代码!

  Date.New;      // 在大多数语言中是非法代码!

⑤ 困难在于类要知道“哪个对象的属性”。回忆一下,对于一个给定类,在运行时可能会有上千个对象。想要获取该类的某个对象的唯一方法是知道该对象的句柄,然后发送消息给它。尔后该对象友好地将属性消息返回给发送消息的类。

⑥ 创建了一个对象(每当执行类操作New时,总是创建一个带有句柄的对象)。然而,这个程序中命名为gl的对象是Glider的实例,通过继承它也是Aircraft的实例。

⑦ 面向对象程序的初始化依赖于你所使用的语言和操作系统。操作系统可以通过三种普通的方式将控制转移给应用程序:

从主函数开始执行,与常规的过程语言一样,在程序启动时获得控制。
自动示例一个程序员定义的类Root的对象,从其实例开始整个程序的执行。
生成一个面向对象浏览环境,通常具有图形界面。然后用户/程序员可以交互式地向适当的类(或对象)发送消息,使程序运行。
⑧ 当关掉计算机时,丢失了内存中的所有对象及其所包含的信息。如果这样对你有影响,则必须在面向对象程序终止前,将信息保存在磁盘上。在面向对象数据库管理系统(ODBMS)中,多少可以直接存储对象。但如果你使用的是关系型数据库,就不得不在存储信息之前将对象信息“分解”成通常的表格形式。

⑨ 当关掉计算机时,对类没有什么影响(对大多数环境而言)。你的类已经编译并保存在永久的磁盘上。这也说明了类和对象之间的区别,前者是永久的形式,而后者是易变的运行单元。

⑩ 在一些语言中,不守规矩的设计者可以设计一些方法,使外界可以“跳过对象的围墙”并直接处理变量。一种方法是通过C++的“友元”方法。与多数其他设计过失一样,这种方法通常具有影响大的罪名。

11.tif 如果你已经为你目前所使用的语言选择了一种术语,考察一下哪个面向对象属性你认为最有价值。如果你选用的语言不是完全面向对象的,你最希望你的语言应具有本章提到的哪些特性?为什么?

12.tif Java实际上只支持本章描述的“继承能力”意义上的单继承。假设类S有下面的语句:

  extends C implements I1,I2
表示S可以访问C的所有操作(Java方法)。换言之,通过extends的构造,S不仅继承了C的接口,而且还继承了C的能力(使接口工作的代码)。然而,通过implements 构造,S继承了责任,但没有继承能力。在这个例子中,S的设计者或程序员对于定义在接口I1和I2中所有操作,负责提供可行的Java方法。

13.tif 下面是你可能用Java重写的机器人程序。假设该算法包含在操作navigate中,它将是类Grid的一个操作(对方格对象的任何访问都通过this)。还假设方格对象被正确地初始化(如以前插入的任何机器人已被删除)。

Public boolean navigate( )


{// 在起始方格中放入一个新机器人,并将机器人导航到正确的结束方格,每一步都显示机器人。如果算法有问题,则返回false;否则返回true。

Hominoid hom = new Hominoid ( );// 创建Hominoid的新实例,由hom表示

  int oneSquare = 1;        // 常量

  int initialTurnCount;

Square startSquare = this.start;

Boolean insertOK = this.insertHominoid(hom,startSquare);

         //如果成功insertHominoid返回true

if (!insertOK) return false

         //如果机器人没有将OK放入方格中,则终止。

    // 将机器人设置为正确的方向

    // 将机器人最多转4次或直到机器人在其前方有清楚的路径

 initialTurnCount = 1;

 while (initialTurnCount <= 4 && hom.facingWall)

    { hom.turnLeft();initialTurnCount++;}

// endwhile结束

this.display();      //显示方格

hom.display();      //显示机器人

while (hom.location != this.finish)

{ if (hom.facingWall)

  {hom.turnLeft();

 if(hom.facingWall) { hom.turnRight();hom.turnRight();}

 // endif结束

} // endif结束

 hom.advance(oneSquare);

 hom.display;

} // endwhile结束

               //机器人成功结束!

return true;

 } //结束导航

本文仅用于学习和交流目的,不代表异步社区观点。非商业转载请注明作译者、出处,并保留本文的原始链接。
时间: 2024-10-24 00:40:37

《UML面向对象设计基础》—第1章1.12节答案的相关文章

《UML面向对象设计基础》—第1章1.9节一般性

1.9 一般性 UML面向对象设计基础 一般性(genericity)指一个或多个类内部使用的类C的结构,仅在运行时(即示例类C的对象时)才提供. 说明一般概念的最好方式是讲述一个不堪回首的故事.当时我还是一名大学生,学习一门数据结构(Data Structures)的课程101.有一个学期,Rossini 教授给我们留了一项作业,设计和编程整数有序平衡二叉树(见图1.22).平衡二叉树的主要特点是所有的叶子在同层上拉平. 在往树中插入另一个整数(如5 ,见图1.23)之前,一切顺利.插入整数5

《UML面向对象设计基础》—第1章1.5节消息

1.5 消息 UML面向对象设计基础 对象通过消息请求另一个对象执行活动.许多消息还具有将信息从一个对象传送给另一个对象的作用.大多数老前辈都将消息列为重要的面向对象特性. 消息(message)是发送对象obj1向目标对象obj2发送请求的载体,申请对象obj2的一个方法. 本节对消息特性进行了剖析,描述了消息参数的特点,发送消息对象的角色,接收消息对象的角色及消息的三种类型. 1.5.1 消息结构 消息由几个含义组成,每个含义在面向对象设计中都十分重要.实际上,本书从头到尾会多次用到消息的特

《UML面向对象设计基础》—第1章1.1节封装

第一部分 引言UML面向对象设计基础"面向对象"术语本身是无意义的."对象"大概是英语中最普通的词了.在字典中查找它的定义如下: 对象:被呈现的或可被感官识别的物体.换句话说,对象可以是任何事物! "面向"一词也不能说明什么含义,定义为"直接针对".因此有下面的定义: 面向对象:直接针对你能想到的任何事物.软件界历史上在讨论"面向对象"的定义上很难达成一致的意见并不奇怪.由于缺乏清楚的定义使得包装成&quo

《UML面向对象设计基础》—第1章1.7节继承

1.7 继承UML面向对象设计基础如果你写了一个类C,后来又发现一个类D 除一些额外的属性和操作外与类C几乎是一样的,你会怎么办呢?一种办法是简单地复制C的所有属性和操作,然后将其放到D中.但这种方法不仅增加了额外的工作,而且复制本身也存在维护的麻烦.更好的方法是让类D向类C"请求使用其操作",这种方法称为继承(inheritance). 继承(从C到D)是指类D在类C中隐式地定义其每个属性和操作,就好象 这些属性和操作是在类D本身中定义一样. C称为D的超类.D称为C的子类. 换言之

《UML面向对象设计基础》—第1章1.11节习题

1.11 习题UML面向对象设计基础①(a)重写机器人hominoid-navigation算法,使其更健壮. (b)你能发现在Grid中定义的操作insertHominoid(hom:Hominoid,location:Square,out insertOK:Boolean)中的问题吗? ② 对象知道自己的句柄吗?如果知道的话,对象如何表示其句柄? ③ 为什么在消息参数中很少使用相同的参数名既作为输入参数又作为输出参数?假设参数表示具有句柄的对象. ④ 在 1.5.3节中,我说过"在纯面向对象

《UML面向对象设计基础》—第1章1.10节本章小结

1.10 本章小结 UML面向对象设计基础 因为"面向对象"在英语中就没有绝对优势的定义,因此,针对面向对象定义的特性从来就没有一致的意见.我本人认为以下特性对面向对象是至关重要的:封装.信息/实现隐藏.状态保持.对象标识.消息.类.继承.多态性及一般性. 面向对象的封装产生一个由表示对象状态的属性及其操作组成的软件结构("对象"),用实现的术语讲,就是操作的方法处理保持对象状态的变量.封装确保对对象内部信息的任何修改(或访问)都必须通过对象的操作. 信息/实现隐藏

《UML面向对象设计基础》—第2章2.4节面向对象的益处

2.4 面向对象的益处 UML面向对象设计基础 本节的题目既迎合愤世嫉俗者又符合盲从者. 一些反对者可能会说面向对象没有什么优点:它仅是一种流派或是一场从西方一些地区引发起的全球性阴谋.而一些激进派则宣称面向对象是一流的并且是所有软件成功的唯一途径.面向对象不仅适用于Windows系统,而且还适用于无所不能的分布式Web体系结构. 这两种说法都太极端.作者认为面向对象是有用的,但不能神化,它还不够完美,其特定实用程序依赖于在软件开发过程中的使用方法. 没有一种有价值的软件工程方法可以成为"当年时

《UML面向对象设计基础》—第2章2.1节面向对象的起源

第2章 面向对象简史 UML面向对象设计基础 前面讨论了面向对象的固有特性,现在来看一下面向对象是如何适用于软件开发的广阔领域. 当听说Wolfgang Pauli教授提出一种新的基本粒子(μ介子,μ- meson或muon)时,Isidor I .Rabi教授曾经立即予以反驳:"谁承认这种说法?"鉴于此事例,我在本章开头部分列出一些对面向对象有贡献的人士.下面将面向对象置于社会环境中,讨论对这种软件方法的看法.然后,将面向对象置于工程环境中,将面向对象与电子学做一个类比.最后,阐述面

《UML面向对象设计基础》—第2章2.2节面向对象的成熟期

2.2 面向对象的成熟期 UML面向对象设计基础 本节介绍软件工业如何促进面向对象时代的真正到来. 老生物学家们常爱发表这样的言论:个体生物重演了生物发展史.其含义是个体生物胚胎的发展通常演绎着生物整体发展的进化过程(如人类胚胎的发育过程).当然在时间上存在很大的差异.个体生物的发展可能只有几个月,而整体生物却世代繁衍. 尽管老生物学家的说法无庸置疑,但在软件工程中却出现了一种新观点:面向对象软件工程的历史重演了传统软件工程的历史.当然在时间跨度上也存在很大的差异.形成成熟的过程和数据库结构花费