ADT 抽象数据类型,由程序员自己定义的数据类型,强调于操作而不需要知道数据的具体存储。
相当于对于内部操作进行了封装以避免客户端获取内部数据的表示方法,相当于用墙隔开了设计者与客户端使用者,借此以避免潜在的危险与bug。
ADT分为可变和不可变数据类型。
ADT可以有4种操作:
①构造器creator,输入一些其它类型的对象,创建一个该ADT对象。例如创建一个新集合new() 或者现实中的构造函数。 ②生产器producer,通过该ADT的旧对象,创建一个该ADT的新对象,例如计算当前集合与S的 交集的方法ins(S)。 ③观察器observer,通过该ADT本身的数据以及传入参数,计算得到其它类型的值。例如检查 集合里是否有x的方法find(x)。 ④变值器mutator,作出“修改ADT内部数据”的行为,是可变对象与不可变对象的本质区别!例 如将x加入集合并返回加入x后的集合大小的方法add(x)。
creator : t* → T producer : T+, t* → T observer : T+, t* → t mutator : T+, t* → void | t | T
设计好的ADT,写好的规约必不可少。ADT的规约里只能使用client可见的内容来撰写,包括参数、返 回值、异常等。
ADT要足以支持client对数据所做的所有操作需要,且 用操作满足client需要的难度要低。而且要么针对具体设计,要么针对抽象设计,不应混合。
ADT要有表示独立性,用户使用ADT时无需考虑其内部实现,ADT内部表示的变化不应影响外部spec和客户端。
测试ADT可以使用上面提到的四种操作,测试creators, producers, and mutators可以调用observers来观察这些 operations的结果是否满足spec; 测试observers时可以调用creators, producers, and mutators等方法产生或改变对象,来看结果是否正确。但如果被依赖的其他方法有错误,可能导致测试结果不成功。
保持不变性和避免表示泄露十分重要,我们必须假设用户会恶意破坏ADT,保持不变性就可以更好发现那些错误。
设计者到使用者相当于从一个设计者关注的表示空间R到用户关注的抽象空间A
R和A之间映射关系的函数
即如何去解释R中的每一个值为A中的每一个值。
AF : R → A
R中的部分值并非合法的,在A中无映射值
RI
描述了什么是合法的的一个集合
设计ADT:(1) 选择R和A;(2) RI --- 合法的表示值; (3) 如何解释合法的表示值 ---映射AF 做出具体的解释:每个rep value如何映射到abstract value。