【软件构造】ADP+OOP——五、抽象数据类型(ADT)

本文深入探讨了抽象数据类型(ADT)的概念,强调了数据抽象、表示独立性和不变量的重要性。ADT关注于操作而非内部表示,允许设计简洁、一致的操作集。不变量是确保ADT正确性的关键,防止表示泄露并保护内部状态。通过示例展示了如何在实际代码中实现表示不变量和抽象函数,以确保ADT的稳定性和安全性。
摘要由CSDN通过智能技术生成

ADP + OOP

五、抽象数据类型(ADT)

阅读资料:

MIT 课程阅读10-抽象数据类型

MIT 课程阅读11-抽象函数与表示不变量

1、抽象和用户定义的类型

除了编程语言提供的基本数据类型和对象数据类型,程序员可以定义自己的数据类型。

数据抽象:由一组操作所刻画的数据类型

传统的类型:关注数据的具体表示

抽象数据类型强调作用在数据上的操作,程序员和客户端只需设计/使用操作,不需要关心数据如何具体存储。

2、类型和操作的分类

类型可分为可变和不可变数据类型两种。

  • 可变类型的对象提供了可改变其内部数据的值的操作

  • 不变类型的对象的操作不改变内部值,而是构造新的对象

抽象类型的操作分类

构造器creators:创建一个该类型的新对象,可能实现为构造函数或静态函数

生产器producers:通过接受同类型的对象创建新的对象

观察器observer:接受一个同类型的对象,返回一个不同类型的对象/值

变值器mutators:改变对象的内容,通常返回void,也可能返回空类型

3、抽象数据类型例子

int是不可变类型,没有变值器

creators:0,1,2…等数字

producers:算数符+,-,*,/

observer:比较符号==,!=,<,>

mutators:无

4、设计抽象类型

  • 设计简洁、少量、一致的操作,组合可实现强大功能
  • 操作充分考虑客户的需求,支持用户的所有可能的计算

5、表示独立性 Representation Independence

表示独立性:客户使用ADT时不需要考虑内部的实现,ADT内部的变化不会影响外部规约(spec)和客户端

6、测试抽象数据类型

  • 调用observers来测试creators,producers,和mutators,观察结果是否满足规约spec

  • 调用creators,producers,和mutators来产生或改变对象,查看结果测试observers是否正确

风险:如果被依赖的方法有错误,可能导致被测试的方法测试结果失效

7、不变量 Invariants

好的ADT会保护自己的不变量。

不变量是一种属性,在程序运行时总是一种状态,不变性是其中的一种

表示泄露:类外部代码可以直接修改内部存储的数据。

Tweet t = new Tweet("justinbieber","Thanks",new Date());
t.author = "rbmllr";

不仅影响不变性,也影响了表示独立性:无法在不影响客户端的情况下改变其内部表示。

处理表示泄露:

public class Tweet{
    private final String author;
    private final String text;
    private final Date timestamp;
    public Tweet(String author,String text,Date time){
        this.author = author;
        this.text = text;
        this.timestamp = time;
    }
    public String getAuthor(){
        return author;
    }
    public String getText(){
        return text;
    }
    public String getTimestamp(){
        return timstamp;
    }
}

8、表示不变量和抽象函数

表示空间:包含值具体的实现实体

抽象空间:包含的是类型设计时支持使用的值,这些值由表示空间抽象出来,客户端看到和使用的值

在这里插入图片描述

开发者关注表示空间R,客户端关注抽象空间A

抽象函数AF:abstraction function表示值到其对应的抽象值的映射,满射非单射

表示不变量RI:rep invariant表示值到布尔值的映射,某个具体的表示是否合法;可看做表示值得一个子集,包含所有合法的表示值,或一个条件描述什么是合法的表示值

public class CharSet{
    private String s;
    // Rep invariant:
    //   s.lenth() is even
    //   s[0] <= s[1] <= ... <= s[s.length() - 1]
    // Abstraction function:
    //   AF(s) = union of {s[2i],...,s[2i + 1]} for 0 <= i < s.length()/2
    ...
}

9、有益的改变

对于不可变的ADT,它在抽象空间的抽象值是不变的,但它内部表示的表示空间中的取值可以变化

10、AF,RI以及表示泄露安全性的注释

在代码中用注释的形式记录AF和RI

精确记录RI(表示不变量):明确说明什么是合法的/不合法的

精确记录AF(抽象函数):解释每一个抽象值

表示泄露的安全声明:说明为什么不会发生表示泄露

    //Abstraction function:
    // AF(labelSet) = 标签的集合
	// AF(IntervalSet) = 各标签对应时间段的集合
    
    // Representation invariant:
	// labelSet中包含所有IntervalSet中的key
    
    // Safety from rep exposure:
    // 设置labelSet 和 IntervalSet为final
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值