软件构造 Java Software(二)

课程总结

抽象数据类型

抽象数据类型与表示独立性:如何设计良好的抽象数据结构,通过封装来避免客户端获取数据的内部表示(即“表示泄露”),避免潜在的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);
    			}
    		}
    	}

总结

没学习那些概念之前,做实验稍显吃力,学习了之后发现不过按图索骥,实现起来又较为简单

猜你喜欢

转载自blog.csdn.net/eliforsharon/article/details/118344152