规约强度:
前置条件越弱,后置条件越强规约条件越强。
前置条件弱意味着输入的范围更大了,需要处理更多的可能输入,也就是实现方法目标的自由度变低了。
后置条件强意味着输出的自由度变低了,实现的自由度也变低了。
1.设计规约
描述:功能单一(内聚性),易理解。
内容:细致丰富,没有歧义性。
强度:高,功能足够明确,应该考虑各种特殊情况。特殊的也不能太过强,防止难以实现的情况。
规约应该尽可能使用抽象类型,给客户端更大的自由度。
前置条件的检查可以看情况在方法中检查,如果代价过大就不应该在方法中检查规约前置条件。
六.抽象数据类型(ADT)(面对对象的理论基础)
表示独立性:能够分离程序中数据结构的形式和对其使用的方式。通过封装来避免客户端来获取数据的内部表示,防止表示泄露。
ADT的特征:不变量、表示泄露、抽象函数AF、表示不变量RI
1.用户自己的定义的数据类型
数据抽象:由一组操作所刻画的数据类型。
抽象类型不再特别关心于数据的具体表示,而是关心关于数据的操作。
2.类型与操作
可变类型与不可变类型:可变提供了可以改变内部数值的操作,而不可变类型不改变内部值而是进行构造新对象。
四种操作
构造器(Creators):构造器可以提供许多特殊的方法,构造器作为一种方法,负责类中成员变量(域)的初始化。实现可能为构造函数或者是静态函数。例子:赋值,new 等。
生产器(Producers):生产期可以通过一个旧的对象来产生一个同样类型的新对象。例子:加减乘除,字符串链接等。
观察器(Observers):根据现有对象返回一个不同类型的对象。例子:大于小于判断,长度判断等。
变值器(Mutators):改变对象的属性。变值器通常无返回值。也可能返回非空类型。
对于返回值为void的方法,必然着这个方法改变了对象的某些内部状态。
3.设计抽象数据类型
提供一组操作,并为其行为设计规约。
(1)设计简洁,一致的操作。通过简单的操作实现复杂操作。
(2)提供的功能要强,要支持用户的各种可能操作。且操作需要满足条件的难度要低。
(3)抽象设计或具体设计,不要进行混合设计。通用类型中包含具体方法会减低抽象数据类型的通用性。具体类型包含通用方法可能导致一些错误。
4.表示独立性
一个好的ADT是通过其操作来刻画的,内部实现与外部使用分隔开。内部的变化也不会影响外部规约与客户端。
5.测试ADT
测试构造器,生产器和变值器可以使用观察器来观察结果是否满足。
测试观察器,可以调用生产器等的方法改变对象,看测试器结果是否正确。
这种测试方法需要保证非测试方法的正确性。
6.不变量
程序在任何时候总是true的性质。是ADT要时刻保持的一种性质。
不变量可以保证程序的正确性,容易发现相关的错误。
保持不变量的方法
可以使用private隔离外部影响。final可以防止对数据的修改。
7.表示不变量的理论基础
表示空间是给实现者观察和使用的而抽象空间是给客户端观察的。
两个空间满足满射,不是满射说明设计有缺陷,不一定会是单射和双射。
这种映射关系称之为抽象函数(AF),即如何将表示空间中的每个值解释为抽象空间中的每个值。
RI是在这个表示空间中合法的值,而AF是将这些值映射到抽象空间中的方法。
对同样一个表示空间可以有不同的RI,甚至同样的R和RI一可以有不同的AF,即解释方法不同。
设计ADT时
(1)选择R和A;(2)合法的表示值;(3)解释合法的表示值;
这些选择和解释都要写到代码中。