ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

【HIT】哈工大2021春软件构造复习(6)

2021-07-06 10:59:51  阅读:340  来源: 互联网

标签:表示 ADT HIT AF 哈工大 2021 空间 不变性 RI


Chapter 6: Abstract Data Type (ADT)

本章重点:

在这里插入图片描述

6.1 Abstraction and User-Defined Types

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

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

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

6.2 Classifying Types and Operations(类型与操作的分类)

可变和不可变数据类型:可变类型的对象提供了可改变其内部数据的值的操作,而对不变数据类型的操作不改变其内部值,而是构造新的对象。

抽象类型操作的分类

Creator(构造器):创建类型的新对象。

通常通过构造函数和静态方法实现。通过静态方法实现的构造器称作工厂方法(factory method)

在这里插入图片描述

Producer(生产器):在已有对象的基础上创建新对象。例如String类的concat()方法,就是输入两个string然后返回它们连接起来得到的string。

Observer(观察器):输入抽象类型的对象,返回其他类型的对象。例如List类的size()方法。

Mutator(变值器):改变对象。例如List类中的add()方法。

变值器通常返回void(此时意味着它改变了对象的某些内部状态),但有时候也返回boolean类型。

在这里插入图片描述

操作举例:

在这里插入图片描述

在这里插入图片描述

6.3. Abstract Data Type Examples

int

构造器: the numeric literals 0 , 1 , 2 , …

生产器: arithmetic operators + , - , * , /

观察器: comparison operators == , != , < , >

变值器:int是不可变类,没有变值器。

String

构造器: String constructors

生产器: concat , substring , toUpperCase

观察器: length , charAt

变值器:String是不可变类型,没有变值器。

List:List是可变类,同时也是一个接口。

构造器:ArrayList and LinkedList constructors,Collections.singletonList

生产器:Collections.unmodifiableList

观察器:size , get

变值器:add,remove,addAll,Collections.sort

一些其他例子:

在这里插入图片描述

6.4. Designing an Abstract Type

规则

设计简洁、一致的操作;
要足以支持用户对数据所做的所有操作需要,且用操作满足用户需要的难度要低。

6.5 Representation Independence(表示独立性)

表示独立性:用户使用ADT时无需考虑其内部如何实现,ADT内部表示的变化不应影响外部规约和客户端。除非ADT的操作指明了具体的前置条件和后置条件,否则不能改变ADT的内部表示。

简单地说,调用者不应依赖其内部private字段,而实现者应该在不检查调用者代码的前提下进行代码更改。

一个例子:不同的字符串表示

在这里插入图片描述

假如其内部表示为:在这里插入图片描述

则相应实现为:

在这里插入图片描述

如果内部表示为(更好):在这里插入图片描述

则相应实现为:

在这里插入图片描述

6.6 Testing an Abstract Data Type

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

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

这样测试的风险在于如果被依赖的其他方法有错误,可能导致被测试方法的测试结果失效。

划分ADT操作的输入空间:

在这里插入图片描述

具体测试实例:

在这里插入图片描述

6.7 Invariants(不变性)

ADT的不变性:在程序运行中程序始终保持不变,例如immutability就是一个典型的”不变量“,在任何时候都表现为相同的值。ADT有责任来保持其不变性而非依赖于用户和其他模块。

为什么需要不变性?因为当ADT保持自身不变性时,容易推理错误发生的地方。

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

一个例子:

在这里插入图片描述

我们该如何保证Tweet类是不可变的?

当出现这种情况时:在这里插入图片描述

不变性和表示独立性均会受到影响。我们可以将代码修改为:

在这里插入图片描述

注:由于timestamp是Date类的而Date是可变的,故timestamp不能避免表示泄露。

在规约中警告用户?只有在复制代价很高的时候,再这么做。

总结:避免表示泄露要注意的几点

(1)将public修改为private final

(2)return时防御式拷贝

(3)return时使用Collections.unmodifiableSet()

6.8 Rep Invariant and Abstraction Function(表示不变性和抽象方法)

在这里插入图片描述

R:表示空间,包括实际实现时的值。

A:抽象空间,包括用户看到和使用的值。

ADT开发者关注表示空间R,而用户关注抽象空间A。

从R空间到A空间的映射是满射,但未必是单射,也未必是双射

抽象函数(AF:R->A):R和A之间映射关系的函数,即如何去解释R中的每一个值为A中的每一个值。如果R中部分值不合法,这些值在A中无映射值。

表示不变性(RI:R->boolean):某个具体的“表示”是否是“合法的”。也可以将RI看作所有表示值的一个子集,包含了所有合法的表示值;或是一个描述了什么是“合法”表示值的条件

一个例子:

在这里插入图片描述

什么决定了AF和RI?

选择某种特定的表示方式R,进而指定某个子集是“合法”的(RI),并为该子集中的每个值做出“解释”(AF)—即如何映射到抽象空间中的值。

当我们有相同的R空间时,可能会有不同的RI:

在这里插入图片描述

当R空间和RI都相同时也可能会有不同AF

AF和RI如何影响ADT设计

设计ADT时要选择R空间和A空间,还要决定合法表示值(RI)和如何解释合法表示值(AF)。

一个例子:

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

断言(assert):在所有可能改变rep的方法中利用assert检查表示不变性,方法是调用checkRep()有助于尽早发现因表示泄露造成的不变性错误。

注:Observer方法可以不用,但是以防万一建议也检查。

6.9 Beneficent mutation(有益的可变性)

有益的可变性(Beneficent mutation):抽象值(空间)永远不可改变,但是在保证表示值映射的抽象值不变的前提下,表示值可以改变。

例如,在上一个例子中,我们在计算时不要求分子和分母不含公约数,但是在将结果输出给用户时,我们要求结果中必须不含公约数:

在这里插入图片描述

这种可变性(mutation)只是改变了R值,并未改变A值。

注:这种有益可变性并不意味着在immutable类中可以随意出现mutator!

6.10 Documenting the AF, RI, and Safety from Rep Exposure

先改private 然后immutable引用返回无所谓 mutable看sets return

看AF是否合理;给AF和R空间的值判断A空间的值

1.Documenting AF and RI

在代码中用注释形式记录AF和RI(给程序员看)。要精确的记录RI:rep中的所有fields何为有效;要精确记录AF:如何解释每一个R值。

2.Documenting rep exposure safety argument

表示泄漏的安全声明(Safety from rep exposure):给出代码并未对外泄露其内部表示的证明。

例:

在这里插入图片描述

对于ADT的规约总结

(1)只能使用用户可见的内容来撰写,包括参数、返回值、异常等。如果规约里要提及“值”,只能使用A空间中的“值”。

(2)规约里也不应谈及任何内部表示的细节,以及R空间中的任何值。

(3)ADT的内部表示(私有属性)对外部都应严格不可见。

(4)在代码中以注释的形式写出AF和RI而不能在Javadoc文档中,防止被外部看到而破坏表示独立性/信息隐藏。

3.How to establish invariants

如何设置不变性

在对象的初始状态不变量为true,在对象发生变化时,不变量也要为true。

设置不变性的要点总结为以下三点:

在这里插入图片描述

6.11 ADT invariants replace preconditions

用ADT不变量取代复杂的前置条件,相当于将复杂的前置条件封装到了ADT内部,取消了对用户输入的限制,转而由程序员解决。

标签:表示,ADT,HIT,AF,哈工大,2021,空间,不变性,RI
来源: https://blog.csdn.net/m0_49375419/article/details/118515307

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有