3.3抽象数据类型
- ADT的操作的四种类型
- 表示独立性
- 表示泄露
- 不变量与表示不变量
- 表示空间,抽象空间,AF
1.ADT的四种操作
ADT是更强调作用于数据上的操作,不管其怎样实现
操作类型
- creator 构造器,用一些东西创建出一个新的对象(用木头造纸)other type->new object
- producer 生产器 用旧的对象产生新的对象(旧纸造新纸)old object->new object
- Observer 观察器 观察一个对象 的特征,返回特征值(观察纸,返回值的厚度)(类型变了)object->other type
- Mutator 变值器 改变对象某个属性(改变纸的厚度)
构造器:构造函数或者静态函数(工厂方法)
---------------------------------------------------------------------------------------------------------------------------------
2.表示独立性(rep independence)
表示独立性: client使用ADT时无需考虑其内部如何实现, ADT内部表示的变化不应影响外部spec和客户端
除非ADT的操作指明了具体的pre-和post-condition,否则不能改变ADT的内部表示——spec规定了client和implementer之间的契约
---------------------------------------------------------------------------------------------------------------------------------
3.表示泄露
可以从外部直接访问某个变量(设为public时)
不仅影响不变性,也影响了表示独立性:无法在不影响客户端的情况下改变其内部表示
防止表示泄露:--private final
但是由于Date是mutable的对象
如果在一个方法里使用getTimestamp方法:
对象的表示不变量Date仍然被改变了
所以我们又需要用到防御式拷贝
但是这样依然有问题 , 在创建Tweet对象之前,为对象属性赋值的date若有引用,仍然可以改变引用指向的对象的值,进而影响内部表示:
这里24个tweet的date属性,引用的是同一个对象,因此会有:
仍然使用防御性拷贝
防御式拷贝就是模仿immutable的,所以说,归根到底就是mutable对象的问题
---------------------------------------------------------------------------------------------------------------------------------
4.不变量
不变量:在任何时候总是true, 由ADT来负责其不变量,与client端的任何行为无关
其在整个生命周期中,总是表现出相同的价值。
(在我看来就是类的成员变量,最好定义为private final,使用imutable的对象 以防止表示泄露)
保持不变性和避免表示泄漏,是ADT最重要的一个Invariant!
---------------------------------------------------------------------------------------------------------------------------------
5.表示不变量与抽象函数
(1)Rep Space表示空间:表示值所处的空间
一般情况下ADT的表示比较简单,有些时候需要复杂表示,
(2) Abs Space 抽象空间:client看到和使用的值
ADT实现者关注R,而用户关注A
(3)抽象函数AF:将表示空间的值映射到抽象空间 不一定是单射,但一定是满射
(4)表示不变量RI: 在表示的过程中,就出现了表示不变性RI:
即某个具体的“表示”是否是“合法的”
也可将RI看作:所有表示值的一个子集,包含了所有合法的表示值
也可将RI看作:一个条件,描述了什么是“合法”的表示值
- 不同的内部表示,需要设计不同的AF和RI
(图一)同样的R 不同的RI 同样的AF
实验时要随时检查RI是否满足:checkRep()--一般是在每个函数返回前检查
在对象的初始状态不变量为true,在对象发生变化时,不变量也要为true
- 构造器和生产器在创建对象时要确保不变量为true
- 变值器和观察器在执行时必须保持不变性。
Rep中不可出现null
---------------------------------------------------------------------------------------------------------------------------------
5.以注释的形式撰写AF和RI
每个类的内部都需要又AF和RI,还要有表示泄露的安全声明
可以用不变量的方式取代precondition