1.设计规约

前置条件:对客户端的约束,在使用方法时必须满足的条件
后置条件:对开发者的约束,方法结束时必须满足的条件
契约:如果前置条件满足了,后置条件必须满足。前置条件不满足,则方法可做任何事情

spec变强:更放松的前置条件+更严格的后置条件
在不冲突的情况下,强规约可以替代弱规约
S2比S1有更严格的后置条件:在满足S1的前置条件的前提下,S2后置条件强于S1的后置条件

Diagramming specifications
某个具体实现,若满足规约,则落在其范围内;否则,在其之外。
软件构造复习2
更强的规约,表达为更小的区域
软件构造复习2
2.抽象数据类型(ADT)

ADT的特性:表示泄漏、抽象函数AF、表示不变量RI(对ADT内部不变量的说明)
ADT组成:Creators(构造器)、Producers(生产器)(从旧对象产生新的对象)、Observers(观察器)、Mutators(变值器)(改变对象属性)
构造器可实现为构造方法或静态函数(静态工厂方法)

表示独立性:client使用ADT时无需考虑其内部如何实
现,ADT内部表示的变化不应影响外部spec和客户端
保持不变量:由ADT来负责其不变量,与client端的任何行为无关
避免表示泄露:采用private,final修饰,采取防御式拷贝

AF(抽象函数)
抽象值构成的空间:client看到和使用的值
软件构造复习2
映射关系:一定是满射,未必是单射,未必是双射,R中的部分值并非合法的,在A中无映射值
检查RI:编写checkRep(),将其放入每个方法中

对immutable的ADT来说,它在A空间的abstract value应是不变的。
 但其内部表示的R空间中的取值则可以是变化的

记录AF、RI
在代码中用注释形式记录AF和RI,写出表示泄漏的安全声明
软件构造复习2
3.面向对象编程(OOP)

接口中被default修饰的方法可以有方法体,被认为是接口的默认方法

重载条件:不同的参数列表,方法名相同
泛型通配符List<?> //类型没有限制 List<? extends Animal> //必须是Animal的子类型 List<? super Animal> //必须是Animal的父类型
子类型规约不能弱于父类型规约

4.ADT和OOP中的“等价性”

引用等价性:==判断
对象等价性:equals()判断

4.1不变类型的等价性:观察等价性,通过get方法判断
对于该类的自定义ADT,需要重写equals(),与hashCode()
重写equals()
软件构造复习2
instanceof:判断左边的实例对象是否是右边类型的实例或子类实例
if中的判断语句也可改为:A.getClass()!=B.getClass()

重写hashCode():等价的对象必须有相同的hashCode,而且hashCode()中的变量应与equals()方法中的变量对应

对于多个变量,可以采用如下方式
软件构造复习2
4.2可变类型的等价性:部分观察等价性,部分行为等价性
如Date,List观察等价性,StringBuilder行为等价性
对可变类型,实现行为等价性即可。 也就是说,只有指向同样内存空间的objects,才是相等的。无需重写这两个函数,直接继承
Object的两个方法即可

扩展

复制引用
软件构造复习2
内存地址相同

复制对象:内存地址不同
浅复制:对象内部引用的其他对象指向原来的地址空间
如:Person a = new Person("1"); Person b = (Person)a.clone();
继承Object的clone()方法是浅复制

深复制:对象内部引用的所有其他对象指向不同地址空间
就要实现Clonable接口,覆盖并实现clone方法,除了调用父类中的clone方法得到新的对象, 还要将该类中的引用变量也clone出来。
软件构造复习2

相关文章: