1.5.2 指定数据和操作(1)
在使用C++实现包之前,必须描述其数据并详细指定与包行为相对应的方法。为了完整地描述这些行为对包中数据的影响,我们将命名方法、选择参数、决定返回类型并编写注释。最终的目标当然是为所有方法编写C++头文件以及注释,但是我们首先用伪代码表示这些方法,然后用UML表示法表示。
注释:在不同的开发阶段使用UML描述类
CRC卡中给出的第一个行为需要一个返回当前包中项数目的方法。这个方法没有参数,返回一个整数。通过伪代码得到了如下的规范,在此使用了UML表示法:
- // Returns the current number of entries in the bag.
- +getCurrentSize(): integer
可以使用返回值为布尔值的方法测试这个包是否为空,这个方法也没有参数。用伪代码表示的规范为:
- // Returns true if the bag is empty.
- +isEmpty(): boolean
现在向包中加入给定对象。将这个方法命名为add,并用一个参数代表新项。可以编写如下的伪代码:
- // Adds a new entry to the bag.
- add(newEntry)
我们或许不想让add返回值,但是如果包满了,则我们无法添加新项。在此情况下应该怎么做呢?
当add无法完成任务时,有两个选择:
什么都不做。由于无法添加新项,因此忽略这个项,包保持不变
包保持不变,但是通知客户无法执行添加操作
第一个选择较为简单,但是客户会疑惑发生了什么。当然,可以将包必须处于未满状态作为前置条件,这样由客户负责避免向一个已经满了的包中添加新项。
第二个选择相对较好,并且也并非困难到无法实现。如何向客户表明添加操作是否成功呢?如果添加操作失败可以抛出异常,但是我们在后面再讨论这个方法,现在采用另一种方法。显示错误消息并不是一个好主意,因为应该让客户控制所有的写输出。因为添加操作只有成功和失败两种情况,因此可以简单地让add方法返回一个布尔值。
这样,可以将add方法更完整地指定为:
- +add(newEntry: ItemType): boolean
其中,newEntry的数据类型为ItemType。在C++片段1中,将讨论使用模板以及typedef语句的实现细节,从而让ADT的数据类型更为灵活。
从包中删除项涉及两种行为:删除某个特定项和删除全部项。假定我们已经命名了这些方法以及所有参数,并开始用伪代码将其指定,如下所示:
- // Removes one occurrence of a particular entry from the bag, if possible.
- remove(anEntry)
- // Removes all entries from the bag.
- clear()
这些方法的返回类型是什么?
如果给定项不在包中,则remove方法无法将其删除。可以让这个方法返回一个布尔值,就像add那样,这样就可以说明是否成功执行。这样,这个方法的UML规范如下所示:
- +remove(anEntry: ItemType): boolean
方法clear可以是void方法:我们只想将包清空,而不需要获取任何项。因此,可以将其规范改进为:
- +clear(): void
其余的行为不会修改包中的内容。其中一个行为计算包中给定对象的数目,其规范可以用伪代码表示为:
- // Counts the number of times a given entry appears in the bag.
- +getFrequencyOf(anEntry: ItemType): integer
另一个方法测试包中是否包含了给定对象。可以用伪代码进行如下指定:
- // Tests whether the bag contains a given entry.
- +contains(anEntry: ItemType):boolean