抽象数据类型ADT
1ADT的解释
数学模型及该模型上的一组操作。或者说一组由操作定义的数据类型。
这说明ADT由两部分构成,一部分是数据,另一部分是在上面定义的操作。举例说明,就像整数Z,以及定义在整数上的加减运算。
2 ADT的操作
Creators构造器:创建该类型的新对象。
Producers生产器:使用一个存在的对象产生一个新的对象。例如String.concat()。
Observers观察器:获取抽象类型的对象并返回不同类型。例如List.size()。
Mutators变值器:用于改变对象属性的方法。例如List.add()。注意,变值器一般返回为void,也可能返回bool值表示操作是否成功。
3设计ADT
好的ADT设计原则
(1)设计简洁一致的操作
(2)要足以支持client所需要的对数据的所有操作,且用操作的难度要低(3)要么抽象要么具体,不要混合——要么针对抽象设计,要么针对具体应 用的设计。
表示独立性
client使用ADT时无需考虑其内部如何实现,ADT内部表示的变化不应影响外部spec和客户端。
客户端不应该依赖具体的实现细节而应该依赖抽象。
除非制定了条件,否则不应该更改ADT内部实现。没有条件时候,客户端不知道到底和你约定了什么。
测试ADT
由于不能直接访问ADT内部的数据域,所以只能调用其他方法去测试被测试的方法。
creator,producer,mutator:用observer来查看变化。
observer:用creator,producer,mutator变化后观察。
注意:如果被依赖的其他方法有错误,可能导致被测试方法的测试结
果失效。
不变量(Invariant)
不变量:程序在任何时候总是true的性质。
为什么需要不变量:保持程序的“正确性”,容易发现错误。
表示泄露: 不仅影响不变量,也影响了表示独立性:无法在不影响客户
端的情况下改变其内部表示。
防止表示泄露:
例如:
1.确保不会返回任何可变对象的直接引用,可以防御拷贝。
2.使用关键字private让rep对外不可见。
最好的办法就是使用immutable的类型,彻底避免表示泄露。
Rep Invariant(RI) and Abstraction Function(AF)
表示空间R:实现者看到和使用的值。
抽象空间A:client看到和使用的值。
抽象函数AF:R和A之间映射关系的函数,即如何将R中的每一个值解释为A中的每一个值。
注意,AF必定是一个满射,但不一定是单射。
表示不变性RI:所有表示值的一个子集,包含了所有合法的表示值。也可以将其看作一个条件,描述了什么是“合法”的表示值。
注意:
同样的表示空间R,可以有不同的RI。
即使是同样的R、同样的RI,也可能有不同的AF,即“解释不同”。
设计ADT:
(1) 选择R和A;
(2) RI — 合法的表示值;
(3) 如何解释合法的表示值 —映射AF。