抽象数据类型(ADT)
Abstraction and User-Defined Types
抽象类型:强调“作用于数据上的操作”,程序员和 client无需关心数据如何具体存储的,只需设计/使用操作即可,并且ADT是由操作定义的,与其内部如何实现无关!
Classifying Types and Operations
可变类型的对象:提供了可改变其 内部数据的值的操作;
不变数据类型: 其操作不改变 内部值,而是构造新的对象
- 构造器:可能实现为构造函数或静态函数
- 变值器:通常返回 void,因为如果返回值为void,则必然意 味着它改变了对象的某些内部状态,但变值器也可能返回非空类型
Designing an Abstract Type
设计好的ADT,靠“经验法 则”,提供一组操作,设计其行为规约 spec
- 设计简洁、一致的操作
- 要足以支持client对数据所做的所有操作需要,且 用操作满足client需要的难度要低
表示独立性
表示独立性:client使用ADT时无需考虑其内部如何实 现,ADT内部表示的变化不应影响外部spec和客户端。
除非ADT的操作指明了具体的pre和post-condition,否则不能改变ADT的内部表示——spec规定了 client和implementer之间的契约。
Testing an Abstract Data Type
测试creators, producers, and mutators:调用observers来观察这些 operations的结果是否满足spec; 测试observers:调用creators, producers, and mutators等方法产生或 改变对象,来看结果是否正确。
风险:如果被依赖的其他方法有错误,可能导致被测试方法的测试结果失效。
不变量
不变量:在任何时候总是true,即由ADT 来负责其不变量,与client端的任何行为无关
目的::保持程序的“正确 性”,容易发现错误
AF与RI
抽象值构成的空间一般是指client看到和使用的值
ADT开发者关注表示空间R,而client关注抽象空间A
需要注意的是R是A的满射未必单射也就未必双射
抽象函数:R和A之间映射关系的函数,即如何去解释R中的每一个值为A中的每一个值。
表示不变性RI:某个具体的“表示”是否是“合法的” ,也可将RI看作:所有表示值的一个子集,包含了所有合法的表示值或是一个条件,描述了什么是“合法”的表示并选择某种特定的表示方式R,进而指定某个子集是“合法”的(RI),并为该子集中的每个值做出“解释”(AF)——即如何映射到抽象空间中的值。
而即使是同样的R、同样的RI,也 可能有不同的AF,即“解释不同”
综上,设计ADT需要做到以下几点:(1) 选择R和A;(2) RI — 合法的表示值; (3) 如何解释合法的表示值 —映射AF做出具体的解释:每个rep value如何映射到abstract value ,而且要把这种选择和解释明确写到代码当中( 在所有可能改变rep的方法内都要检查rep )
面向对象的编程
接口
接口:确定ADT规约;类:实现ADT 也可以不需要接口直接使用类作为ADT,既有ADT定义也有ADT实现,但实际中更倾向于使用接口来定义变量
接口的使用打破了抽象边界,接口定义中没有包含constructor,也无法保证所有实现类中都包含了同样名字的constructor。所以客户端需要知道该接口的某个具体实现类的名字
继承
(严格继承:子类只能添加新方法,无法重写超类中的方法)
重写的函数需要保证完全同样的signature
其中父类型中的被重写函数体不为空:意 味着对其大多数子类型来说,该方法 是可以被直接复用的,而对某些子类型来说,有特殊性,故重写父类型中的函数,实现自己的特殊要求
如果父类型中的某个函数实现体为空, 意味着其所有子类型都需要这个功能, 但各有差异,没有共性,在每个子类中均需要重写,重写之后复用了父类 型中函数的功能,并对其进行了扩展
注意: 重写的时候,不要改变原方法的本意
如果某些操作是所有子类型都共有, 但彼此有差别,可以在父类型中设计 抽象方法,在各子类型中重写
所有子类型完全相同的操作, 放在父类型中实现,子类型中无需重写。
有些子类型有而其他子类型无 的操作,不要在父类型中定义和实现,而应在特定子类型中 实现。
重载:多个方法具有同样的名字,但有不同的参数列表或返回值类型 价值:方便client调用,client可用不同的参数列表,调用同样的函数
静态多态根据参数列表进 最佳匹配
静态类型检查 在编译阶段时决定要具体执行哪个方法
参数多态与泛型编程
泛型编程围绕从具体有效的算法中抽象出来的想法,以获得可以与不同数据表示形式组合以生成各种有用软件的泛型算法
子类型的规约不能弱化超类型的规约。
子类型多态:不同类型的对象可以统一的处理而无需区分