软件构造MIT学习心得

MIT Reading 抽象数据类型学习心得

(软件构造)

抽象数据类型

定义

抽象数据类型 = 逻辑结构 + 抽象运算,也就是抽象数据类型是建立在逻辑结构上的一些抽象的运算。主要用来实现分离,封装和信息隐隐藏,我们将其(也就是常说的ADT)定义为

ADT <抽象数据类型名>
{
数据对象:<数据对象的定义>
数据关系:<数据关系的定义>
基本操作:<基本操作的定义>
}
控制对类的访问

简单说就是我们在写程序时候,例如我们使用修饰符声明类,在这种情况下,该类对所有所有类都可见,如果类没有修饰符,一般就只能在自己包中可见。在成员级别,可以使用修饰符或无修饰符,并且具有相同的含义。
修饰符指定只能在其自己的类中访问该成员。修饰符指定成员只能在其自己的包内中访问,此外,还可以由其类的子类在另一个包中访问。

我们从Oracle官网java文档就能看到每个修改器允许的成员的访问

在这里插入图片描述
C++中使用公有,保护,私有表明类是否有权访问由访问级别定义的成员

1. 第一列我们能看到类始终可以访问其自己的成员。 
2.  第二列指示与类位于同一包中的类是否有权访问该成员。 
3. 第三列指示在此包之外声明的类的子类是否有权访问该成员。  
4. 第四列指示所有类是否有权访问该成员。

一般我们使用来自另一个源的类时,使用这种方法就可以知道自己的类能访问哪些成员;其次编写类时,需要决定每个成员变量和类中的每个方法应具有的访问级别。

再来谈谈什么我对于抽象的理解
说白了之所以会有抽象数据类型,我认为和我们经常说的模块化,封装,还有信息隐藏等专用词紧紧相关的,不过我们在写的时候,经常使用的是方法的抽象,我们可以将抽象类型的值比作硬壳,不仅隐藏单个函数的实现,还隐藏一组相关函数(类型的操作)及其共享的数据(存储在类型值内的私有字段)。今天来谈谈数据抽象类型是怎么操作的。

抽象类型操作
 1. 创建者创建类型的新对象。创建者可以采用其他类型的值作为参数,但不能将正在构造的类型的对象。
 2. 生产者从该类型的一个或多个现有对象创建新类型的对象。例如,方法是一个生产者:它需要两个字符串并生成一个新字符串,表示它们的相关联。
 3. 观察者获取抽象类型的对象并返回不同类型的对象。
 4. 修改器更改对象。(例如,通过向末尾添加元素)对列表进行变异。
抽象数据类型举例

int是JAVA原始数据类型

 1. 创建者:数字文本,例如0   1   2 
 2. 生产者: 算术运算符,例如常用的+   -   *   / 
 3. 观察者: 比较运算符 ,例如==    !=    <    >
 4. 修改器:无(不可变)

String是 Java 的字符串类型

1. 创建者:构造函数,静态方法,如String valueOf 
2. 生产者:  如concat substring toUpperCase
3. 观察者:如length charAt 
4. 修改器:无(不可变)

List是 Java 的列表类型

1. 创建者:如ArrayList  Linked  ListList.of 
2. 生产者:如Collections.unmodifiableList
3. 观察者:如size  get 
4. 修改器:如Collections.sort  add  remove  addAll
心得

通过部分对于抽象数据类型的举例,我们得知,在数据类型使用时,我们要灵活多变,使用紧密相关的组和,而不是进行复杂的操作,这样往往会造成代码复杂,添加修改操作不易,且并不一定复杂的操作就见的好。还有,我们的操作集得足够,一个好的测试是检查是否可以提取类型对象的每个属性,要是连基本操作都没有,我们就很难获取最基本的信息。

独立性

一个好的抽象数据类型应该是表示独立的。这意味着抽象类型的使用独立于其表示形式,因此表示形式的变化对抽象类型本身以外的代码没有影响。

作为实现者,除非其操作完全指定了先决条件和后置条件,这样客户端就知道可以放心更改什么,否则完全无法更改 ADT 的表示形式。我们要先知道表示独立性意味着什么,以及它有什么用,为什么有用。
我们看看字符串的不同表示形式

/** MyString represents an immutable sequence of characters. */
public class MyString { 
    public static MyString valueOf(boolean b) { ... }
    
    public int length() { ... }

    public char charAt(int i) { ... }

    public MyString substring(int start, int end) { ... }
}

这些公共操作及其规范是允许此数据类型的客户端知道的唯一信息。但是实现数据类型需要表示形式。通过具体的代码我们来看看实际怎么用

public static MyString valueOf(boolean b) {
    MyString s = new MyString();
    s.a = b ? new char[] { 't', 'r', 'u', 'e' } 
            : new char[] { 'f', 'a', 'l', 's', 'e' };
    return s;
}

public int length() {
    return a.length;
}

public char charAt(int i) {
    return a[i];
}

public MyString substring(int start, int end) {
    MyString that = new MyString();
    that.a = new char[end - start];
    System.arraycopy(this.a, start, that.a, 0, end - start);
    return that;
}

我们通过上面的定义方法可以看到
String.valueOf一般情况下,如果是确定类型的null传入,返回的是字符串“null”,而如果直接传入null,则会发生错误。
length定义长度
charAt返回指定索引处的字符
substring提取字符串中介于两个指定下标之间的字符

我上面提到String.valueOf的用法,以及长度定义出现的错误,如果输入负数,也是不行的,那么我们就得在输入时必须检查它们的参数是否在有效范围内。
例如此代码在客户端的一部分结构下图,此数据类型是不可变的,因此操作我们就不必将字符复制到新数组中。它可以指向原始对象的字符数组,并跟踪新子字符串对象表示的开始和结束。
在这里插入图片描述
如果我们将上面的代码就行优化修改

public static MyString valueOf(boolean b) {
    MyString s = new MyString();
    s.a = b ? new char[] { 't', 'r', 'u', 'e' } 
            : new char[] { 'f', 'a', 'l', 's', 'e' };
    s.start = 0;
    s.end = s.a.length;
    return s;
}

public int length() {
    return end - start;
}

public char charAt(int i) {
  return a[start + i];
}

public MyString substring(int start, int end) {
    MyString that = new MyString();
    that.a = this.a;
    that.start = this.start + start;
    that.end = this.start + end;
    return that;
}

那么在客户端就会生成不一样的结构,这种情况下,客户端仅依赖于其公共方法的规范,而不是其私有字段。因此我们可以进行此更改,而无需检查和更改所有客户端代码。
在这里插入图片描述
这样我们的抽象数据类型的使用才更好的独立于其表现形式。

java 中的ADT

在这里插入图片描述
1,如第一个在Java中使用接口和类定义抽象数据类型;还可以使用枚举定义抽象数据类型,在定义枚举项时,多个枚举项之间使用逗号分隔,最后一个枚举项后需要给出分号,但如果枚举类中只有枚举项(没有构造器、方法、实例变量),那么可以省略分号。
2,在生产者,观察者等操作使用静态方法或实例方法。右边举了些相关的不同操作可用到的方法,简单来说,我们使用ADT只需要了解操作就行,不需要实现详细信息。

心得

ADT是仅由保存的数据类型和可能在这个数据类型上进行的操作定义的,因此ADT在设计时用的封装和信息隐藏的思想,使我们在使用时,仅需要了解使用操作即可。
抽象数据类型的特点就是上面提到的创建者,生产者,观察者,修改器。
以及抽象数据类型的独立性通过上面例子可以清楚独立性允许抽象数据类型的实现进行更改,而无需更改其客户端。
在学习完抽象数据类型后,也对其很多细微的地方有了更多的了解,仅仅在课堂上学到的抽象数据类型的基本定义和ADT的简单使用是不够的,在今后的学习中,还需要更深入的进行研究。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值