第七章 面向对象的编程
1.静态类方法成员公用一个栈。
2.一个类可以实现多个接口(从而具备了多个接口中的方法)。一个接口可以有多种实现类。接口:确定ADT规约;类:实现ADT。也可以不需要接口直接使用类作为ADT,既有ADT定义也有ADT实现。
3. (1) 接口中不能提供任何构造函数。(2) 返回值不能是接口类型的子类型,如ArraySet。(3) 接口中的函数要全部实现,contains没实现。前两个能检测出来,后两个检测不出来。
4.工厂方法构造器:直接return 一个具体的实现类。
以增量式的为接口增加额外的功能而不破坏已实现的类。通过default方法,在接口中统一实现某些功能,无需在各个类中重复实现它,直接调用即可。
5.严格继承,子类只能添加新方法,无法重写超类的方法。此类方法在父类中用final修饰。
6.子类不应增加新的public方法。若父类如果父类型中的某个函数实现体为空,意味着其所有子类型都需要这个功能,但各有差异,没有共性,在每个子类中均需要重写。
7.如果在子类构造器中调用父类构造器,那么父类构造器一定要写在最开始的部分。
8.抽象类与接口的关系。接口是有抽象函数组成的抽象类。
Concrete class à Abstract Class à Interface
9. 如果某些操作是所有子类型都共有,但彼此有差别,可以在父类型中设计抽象方法,在各子类型中重写。接口中所有的方法隐式的加了abstrat。
10.重点:多态、子类型、重载。
特殊多态:函数名称相同,但是调用完全不同。
重载:多个方法具有同样的名字,但有不同的参数列表或返回值类型
价值:方便client调用,client可用不同的参数列表,调用同样的函数
11.静态多态。根据参数列表进行最佳匹配。在编译阶段决定执行哪个方法,以及静态检查。
一些合法重载的样例:
- 重写重载判断:
- 参数化多态主要强调了泛型方面的内容。
- 子类型多态:子类型的规约不能弱化超类型的规约
- Instanceof方法:看一个object是否属于一个class。尽量不用。
- 重写toString:
17.问题:
解答:
18.习题解答:
第八章 ADT与OOP的等价性
1.AF映射到同样的结果,那么久等价。AF(a)=AF(b)。则a和b等价。
2.从client角度看等价性:也就是观察等价性(使用观察器)。
3.observation,说白了就是对Objects(对象)使用方法。
4.如果只有构造器,也可以通过AF来判断是否等价。
5.==:即引用等价性,只有两个引用所指向的内存空间相同,那么才相等。
.equals:对象等价性。在自定义ADT时,需要重写Object的equals。
6. == 对基本数据类型,使用==判定相等。如果用==,是在判断两个对象身份标识 ID是否相等(指向内存里的同一段空间)
7. 在Object中实现的缺省equals()是在判断引用等价性。这不是所期望的,于是需要重写而不是重载。我们希望是对象等价性
8. equals的实例,首先进行null值的判断。一旦等价,等价的对象必须有相同的哈希值(HashCode)。
9.instanceof:看一个object是不是某种特定类的实例。这是动态检查,而非静态检查。
10. 重写了equals,改变了判断相等的方式,就要重写hashCode方法。
11.可变类型的等价性:
观察等价性:在不改变状态的情况下,两个mutable对象是否看起来一致。
行为等价性:调用对象的任何方法都展示出一致的结果。
12.对于可变类型,实现行为等价性即可,也就是说,不用重写equals和hashcode函数。不可变型:两个都要重写。
13. 观察等价性是在某一时间点满足,行为等价性是在一条时间线上的任意区间满足。
14. 这里的b1和b3是指向同一个地址的两个引用。因为b3没有new。可以看作是b1.remove(“b”);b3=b1;
引用等价性:地址相同。
观察等价性,只调用observer,producer和creator的方法,它测试的是这两个索引在当前程序状态下“看起来”相等。
行为等价性:相同的操作能得到相同的结果。
15.例题:true false true
第九章面向复用的软件构造技术
1.抽象的类,是可复用的类。
很大的适应性 降低成本和开发时间 充分的测试à高可靠 标准化、一致化
针对性不强à性能差
2.判断题:最主要的复用在代码层,但是软件构造过程中的任何实体都可能被复用。
3. 白盒复用:源代码可见,可修改和扩展。复制已有代码到正在开发的系统,进行修改。可定制化程度高。对其修改增加了软件的复杂度,且需要对其内部充分的了解。
黑盒复用:源代码不可见,不能修改。只能通过API接口来使用,无法修改代码。简单,清晰。适应性差些。
4.LSP:
5. Behavioral subtype:
子类型需要实现抽象类型中的所有未实现方法
子类型中重写的方法,必须有相同或子类型的返回值
子类型中重写的方法,必须使用同样类型的参数
子类型中重写的方法,不能抛出额外的异常
– Same or stronger invariants 更强的不变量
– Same or weaker preconditions 更弱的前置条件
– Same or stronger postconditions 更强的后置条件
6.LSP:强行为子类型化。并且有以下原则:
7.协变:父类型à子类型:具有越来越具体的specific 。返回值类型:不变或变得更具体。 异常的类型:也是如此。
8.逆变:参数类型越来越抽象。但在java中不允许,因此下面例子被视为重载。
9.首先,数组是协变的。
10.类型擦除:
List之间不存在任何的父子关系,不能直接赋值:
11. 必考,任何泛型类的父类都是Object;只要泛型类型不同,它们之间就不存在任何的父子关系。Box<Number>和Box<Integer>没有任何关系。尽管Integer是Number的父类。
12.尽管用了List<Object>但是仅仅能输出Object instance的列表,所以用到了通配符。可以用 Object j = integer (); List list= new ArrayList();
13.常考:
super Integer 包括Number Integer,super Number 只包括Number。所以 super number是super integer的子类。
14.委托:把一项工作交给另外一个单独的类完成。
分为明确委托和隐式委托。
隐式command:不会直接指定由哪个对象完成功能。
简单委托的例子:首先建立对象a,然后用b的构造器,来建立a与b之间的委托。
15.运用委托进行函数扩展。
- 如果子类只复用父类的一小部分方法, 那么可以不用继承,而用委托实现。下面是继承和委托的区别。委托是需要在被委托类中创建一个委托类实例,如果委托类是class,那么用构造器即可,如果委托类是接口,就用静态empty函数返回一个实现此接口的类。
- 委托在Obejct层面,而非class层面。
- 鸭子飞叫例子: