第二次实验与相关课程总结
- 课程总结
- 抽象数据类型
- 可变数据类型
- 不可变数据类型
- operations of an abstract type
- 表示独立性
- 测试抽象数据类型
- 不变量
- Abstraction Function
- 面向对象
- 接口Interface
- 重载与重写
- 抽象类
- 泛型
- 第二次实验总结
- 关于测试优先
- 关于Safety from rep exposure和Representation invariant
- 关于文件读入
- 总结
课程总结
抽象数据类型
抽象数据类型与表示独立性:如何设计良好的抽象数据结构,通过封装来避免客户端获取数据的内部表示(即“表示泄露”),避免潜在的bug——在client和implementer之间建立“防火墙”
可变数据类型
可变类型的对象:提供了可改变其内部数据的值的操作,例如List
不可变数据类型
不变数据类型: 其操作不改变内部值,而是构造新的对象 ,例如int,String
operations of an abstract type
构造器:可能实现为构造函数或静态函数
变值器:改变对象属性的方法,通常返回为void
观察器:观察对象属性,如The size() method of List
生产器:从旧的对象中创建一个新的对象,如concat() method of String
表示独立性
client使用ADT时无需考虑其内部如何实现,ADT内部表示的变化不应影响外部spec和客户端。
测试抽象数据类型
测试creators, producers, and mutators:调用observers来观察这些operations的结果是否满足spec;
测试observers:调用creators, producers, and mutators等方法产生或改变对象,来看结果是否正确。
不变量
immutability是典型的不变量。immutable的抽象数据类型不能有变值器。对于一些属性不变量,采用private final进行修饰,同时采用防御式编程来保证其不变性。
Abstraction Function
由表示空间映射到抽象空间称为AF。
ADT开发者关注表示空间R,client关注抽象空间A,
它是满射但未必单射,也未必双射。
面向对象
接口Interface
Interface和Class: 定义和实现ADT
接口之间可以继承与扩展
一个类可以实现多个接口
一个接口可以有多种实现类
接口中只确定ADT规约而不具体实现方法,实际当中更倾向于使用接口来定义变量。
使用接口来完成信息隐藏,客户端仅使用接口中定义方法,客户端无法直接访问属性。
重载与重写
关于重写/覆盖:若超类中加了final修饰则无法重载,重写的函数的具体使用是在运行时决定,重写的函数参数与原函数相同。
关于重载:多个方法具有同样的名字,但有不同的参数列表或返回值类型,方便client调用,client可用不同的参数列表,调用同样的函数,重载函数是在编译时进行的静态类型检查。
抽象类
介于接口与类之间,如果某些操作是所有子类型都共有,但彼此有差别,可以在父类型中设计抽象方法,在各子类型中重写
泛型
泛型是一种类型变量,泛型类,泛型接口,泛型方法,其定义中包含了类型变量
第二次实验总结
关于测试优先
设计测试样例时避免重复造轮子,看似写了很多行测试样例,但却没有实际发现错误,同时对于equals和==这部分测试要多留心。
关于Safety from rep exposure和Representation invariant
对于表示的独立性采用checkRep来进行检查,checkRep使用assert语句
如assert vertices2.equals(vertices);
对于表示泄露的预防,所有属性都采用private final 修饰,并且都采用Collections.unmodifiableSet
或者new 一个新值来进行防御式拷贝。
关于文件读入
在第一次实验中采用了一种文件读入方法,这里采用另一种文件读入
打开文件输入流,用scanner按行读入,然后采用分隔符或正则语言进行匹配
InputStream is = new FileInputStream(corpus);
Scanner scan = new Scanner(is);
while(scan.hasNext()) {
List<String>inputString = Arrays.asList(scan.nextLine().split(" "));
Iterator<String>it = inputString.iterator();
String lastString = new String();
String nowString = new String();
while(it.hasNext()) {
lastString = nowString;
nowString = it.next();
nowString = nowString.toLowerCase();
graph.add(nowString);
int nowWeight;
if(lastString.isEmpty() == false) {
nowWeight = graph.set(lastString, nowString, 0);
graph.set(lastString, nowString, nowWeight + 1);
Map<String, Integer>targets = graph.targets(lastString);
}
}
}
总结
没学习那些概念之前,做实验稍显吃力,学习了之后发现不过按图索骥,实现起来又较为简单