ADT

三世轮回 提交于 2020-11-01 11:33:53

需要读的reading MIT6.031 12,13,14

ADT:abstract data type 抽象数据类型

抽象类型:强调“
作用于数据上的操作”,程序员和
client
无需关心数据如何具体存储的,只需设计
/
使用操作即可。
ADT
是由操作定义的,与其内部如何实现无关!

 

AF:abstraction functions 抽象函数

RI:representation invariants 表示不变量

 

ADT和RI:如何设计良好的数据结构,通过封装来避免客户端获取数据的内部表示(即表示泄露)

避免潜在的bug--在client和implementer之间建立防火墙

ADT的特性:

Invariant  不变量

representation exposure 表示泄露

abstraction functions(AF) 抽象函数

 

 

Mutable and immutable types

可变类型的对象:提供了可改变其
内部数据的值的操作
 
不变数据类型:
其操作不改变
内部值,而是构造新的对象
 
有时一种类型会提供两种类型,可变数据类型和不可变数据类型
就像StringBuilder是String的可变版本
 
一个抽象类型的操作可以分为以下四种:
Creater:构造器
构造器:可能实现为构造函数或静态函数 就像new ArrayList(),或者静态方法Arrays.asList()(这种静态方法通常叫做 factory method 工厂方法);
Producer:生产器 利用旧的对象产生新的对象 例如:String中的concat();
Observer:观察器 将对象当作抽象类型,并返回不同类型的对象 例如:List中的size();
Mutators:变值器 改变对象属性的方法,例如List中的add();
通常返回void ,意味着它改变了对象的某些内部状态,但也可能返回非空状态,比如Boolean或者改变的值本身。
 
 
一些ADT的例子:
1,int是immutable的,所以他没有mutators
2,String是immutable的,也没有mutators

 

3,List是可变的 mutable

并且List是一个接口,需要其他调用这个接口的类(比如ArrayList,LinkedList)去具体实现它内部的方法

如何设计一个AT (抽象类型)?

设计好的ADT,靠“经验法则”,提供一组操作,设计其行为规约spec

1,设计简洁,一致的操作

不要添加只对某种特定的数据类型才有意义的操作。

2,要足以支持client对数据所做的所有操作需要,且用操作满足client需要的难度要低

3,要么抽象,要么具体,不要混合--要么针对抽象设计,要么针对具体应用的设计

Representation independence(表示独立性)

含义:用户使用ADT时无需考虑其内部如何实现,ADT内部表示的变化不应影响外部的spec和客户端。

 除非ADT的操作指明了具体的pre-和post-condition,否则不能改变ADT的内部表示——spec规定了client和implementer之间的契约。

要用到defensive copy

 

 

 如何测试ADT

测试creators, producers, and mutators:调用observers来观察这些operations的结果是否满足spec;

测试observers:调用creators, producers, and mutators等方法产生或改变对象,来看结果是否正确。

 

 

invariant 不变量

一个好的ADT的重要的属性是他有自己的不变量

在任何时候都是true的

并且不变量由ADT负责,与客户端的任何行为无关

 

为什么需要不变量?

保持程序的正确性,容易发生错误

就像String如果是个可变量,那么在所有使用String的地方,都有可能会出错,需要检查其是否发生了改变。

如何保证对象是不变的呢?

1,将属性访问权限设置为private,在类外只能用方法来获取

2,final关键字也会起到作用

3,(表示泄露)在一个immutable的对象中引用mutable的对象,也会变成mutable的 ,那么如何解决呢?

这要用到defensive copying:复制一个mutable的对象来避免引用造成的表示泄露

 

copy和clone()

mutable类型通常有复制构造器来让我们创建一个已存在实例的副本实例

或者可以用clone()来复制一个mutable的类型,但这只支持一部分类型

 

 

除非迫不得已,否则不要寄希望于客户端上,而是要保证自己的invariants,并避免表示泄露

最好的办法就是使用immutable的类型,彻底避免表示泄露。

 

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!