第三章:ADT与OOP (第四节)
3.4 OOP
---------------------------------------------------------------------------
1.类:
类由类成员变量与类成员方法组成,每个对象都有一个类
(用.运算符获得类成员变量与类成员方法,他们都是与一个具体的类相联系)
静态方法/变量:不与任何一个类相关
区别:
类方法需要new 之后才能调用,而静态方法则不需要
---------------------------------------------------------------------------
2.接口 抽象类 具体类
接口和类:定义和实现ADT,接口之间可以继承,一个类可以实现多个接口,接口可以被很多类实现,就有了很多种实现策略
接口确定了ADT的规约,class来实现ADT。
抽象类中可以有抽象方法,也可以有具体的方法,抽象类是用来被继承的,其抽象方法需要在子类中具体实现。
---------------------------------------------------------------------------
3.继承和重写
重写的函数除了内部实现和父类中的函数不一样外,其余的必须全部相同,实际执行那个函数在运行时才能决定。
重写之后super()利用了父类中的功能并对其进行了扩展
---------------------------------------------------------------------------
4.多态
- 特殊多态--重载:多个方法具有同样的名字,但有不同的参数列表或返回值类型
(Overload是 静态类型检查) 与重写的区别:
- 参数化多态:泛型 (泛型类与泛型接口) 常用的集合类集是通过泛型实现的,Lab3中涉及到了很多,泛型接口可以通过泛型类或者非泛型类实现 泛型不能使用instanceof()关键字
- 子类型多态:不同类型的对象可以统一处理而无需区分(is_a关系)子类型的规约不能弱化超类型的,且是静态类型检查。如果A是B的子类型,可以由A转到B,但不能由B转到A(拒绝向下转型)子类可以转到父类,但是父类不能转向子类。(LSP)
---------------------------------------------------------------------------------------------------------------------------------
5.equals()与== hashcode()
==判断的是引用等价性,即指向的是不是同一个内存地址,基本数据类型采用的是这种判断(判断ID)equals()判断的是对象等价性,对象数据类型采用的是这种判断(判断每个成员变量的值是否相等)
每次新建ADT的时候都需要重写equals()(默认的是引用等价性)
equals满足自反,对称,传递关系
如果两个对象equals(),他们的hashcode()也必须相等,但是实际上,这两个对象存在堆的不同位置,不可能由相同的hashcode()。因此hashcode()必须被也重写。
hashcode()需要判断所有的成员变量。
---------------------------------------------------------------------------------------------------------------------------------
6.观察等价性与行为等价性
观察等价性:不改变状态的情况下,两个mutable是否看起来一致
行为等价性:调用对象的任何方法产生的都是一致的结果
(!!!对不可变对象来说,行为等价性与观察等价性是一样的,因为他们不可能有变值器)
对可变的数据类型:往往实现严格的观察等价性
equals()对可变类型:实现行为等价性,所以无需重写这两个函数