软件构造lab2回顾
前言
临近期末考试,开始对知识点进行整理,对课程布置的实验进行回顾。经过反复对比,感觉还是动手实验对知识获取的帮助最大,逐步解决问题的过程让自己对课上知识的理解更深入了一些。Lab2这一部分的的主要内容是ADT和OOP,实验目的也是抽象数据型的实现,以及面向对象编程。以下是对Lab2这一实验过程中遇到的一些事物做的简单回顾,课程中涉及到的其他重要知识点将在以后慢慢总结。
内容
一. 实验目标概述
本次实验训练抽象数据类型(ADT)的设计、规约、测试,并使用面向对象编程(OOP)技术实现 ADT。具体来说:
针对给定的应用问题,从问题描述中识别所需的 ADT;
设计 ADT 规约(pre-condition、post-condition)并评估规约的质量;
根据 ADT 的规约设计测试用例;
ADT 的泛型化;
根据规约设计 ADT 的多种不同的实现;针对每种实现,设计其表示(representation)、表示不变性(rep invariant)、抽象过程(abstraction function)
使用 OOP 实现 ADT,并判定表示不变性是否违反、各实现是否存在表示泄露(rep exposure);
测试 ADT 的实现并评估测试的覆盖度;
使用 ADT 及其实现,为应用问题开发程序;
在测试代码中,能够写出 testing strategy 并据此设计测试用例。
二. 涉及到的一些知识
(一)代码覆盖度测试
实验中主要采用Eclemma对测试用例的覆盖度进行测试,在eclipse上的使用方式如下:
1.准备好要测试的代码和测试用例;
2.右键项目->选择Coverage As->Java Application,便可以完成覆盖度测试。显示结果将给出各测试用例的覆盖度,如图所示:
打开被测试的类,其中代码背景颜色被涂成红色的部分即为未覆盖的部分,注意对项目进行覆盖度测试时,只有当被测试的代码覆盖完整时,才会显示绿色,因此未被测试的类中的代码也会一并标记为红色。
(二)对象的存储--对象容器
用来盛装对象的工具,其特点不只在于能够对某一类对象进行存储,而且Java对每一种容器本身也提供了不少相应的方法,使得对象容器使用起来将要简单很多。
1.对象列表
示例如下:
ArrayList<String> l = new ArrayList<String>()
对象列表ArrayList是一个有顺序的列表,其下标索引从0开始。对象在该列表中的存储是有序的,因此与集合Set不同,我们可以通过下标对ArrayList中的元素进行访问。它的优点在于随机访问元素快,但是在中间插入和移除比较慢。
实验中用到的除了基本的size等方法,以下几种方法让我印象较为深刻:
add(int index, Object element):在列表的指定位置插入指定元素。
set(int i, Object element):将索引i位置元素替换为元素element并返回被替换的元素。
个人认为,对象列表和C语言中的数组类似,既可以直接操作、寻找对象,也可以通过下标进行操作,但其元素的个数不固定,长度可变,操作时更加灵活。
2.集合容器
示例如下:
Set<String> set = new HashSet<String>();
Set和数学中集合的概念类似,元素具有唯一性和无序性。所以Set最常用的就是测试归属性,很容易的询问出某个对象是否存在Set中。而若是要获得确定元素顺序的集合,可以用treeset来进行存储。
Set具有和Collection完全一样的接口,继承相应的方法但没有额外的功能,只是表现的行为不同。
3.哈希表
示例如下:
Map<String, Integer> m = new HashMap<String, Integer>();
Map接口就像图表,关键字与关键字的值具有对应关系。类似于日常使用的字典,它根据键的hashCode值存储数据,也就是键-值对的方式存储,因此大多数情况下可以通过键名直接定位到它的值。Map具有很快的访问速度,但其遍历顺序却是不确定的。 注意HashMap最多只允许一条记录的键为null,允许多条记录的值为null。
HashMap很特别的特点就是,我们可以根据关键字和关键字的值分别对表中的对象进行寻找、修改等操作。
(三)遍历访问容器中的对象--迭代器
Java Iterator(迭代器)不是一个集合,它是一种用于访问集合的方法,可用于迭代 ArrayList 和 HashSet 等集合。它是 Java 迭代器最简单的实现,ListIterator 是 Collection API 中的接口, 它扩展了 Iterator 接口。
迭代器的使用使不可变数据型对象容器的遍历等操作变得更加方便,比如删除操作。
迭代器的两个基本操作是 next 、hasNext 和 remove:方法it.next() 会返回迭代器的下一个元素,并且更新迭代器的状态;方法hasNext() 会返回布尔值,用于检测集合中是否还有元素;而方法remove()的用途则是将迭代器返回的元素删除。
以下是写实验时设计的一个使用迭代器实现的方法:
@Override public boolean remove(L vertex) {
Iterator<Vertex<L>> V = vertices.iterator();
while(V.hasNext()) {
Vertex<L> v = V.next();
if(v.Getname().equals(vertex)) {//remove the vertex itself
V.remove();
checkRep();
return true;
}
else {
if (v.Getsources().containsKey(vertex)) {//remove the vertex from related maps(as source)
v.removesource(vertex);
}
if (v.Gettargets().containsKey(vertex)) {//remove the vertex from related maps(as target)
v.removetarget(vertex);
}
}
}
checkRep();
return false;
}
总结
实验2中还有很多较为核心的内容没有列出,文章只给出了一些Java语法及测试的使用方法,一些其他重要的内容将在以后总结。