ADT和OOP中的等价性
1.等价关系
ADT:对数据的抽象;体现为一组对数据的操作
AF:内部表示—>抽象表示
**基于AF定义ADT的等价操作
等价关系:自反、对称、传递
2.不可变类型的等价性
从AF的角度:AF映射到同样的结果—>等价
从外部观察者角度:对两个对象调用任何相同的操作都会得到相同的结果—>等价
3.==与.equals()
==:引用等价性,即是否指向内存中同一地址(在快照图中指向同一个圈圈)
?对基本数据类型使用
.equals():对象等价性,自定义ADT时需要重写Object的equals()
?对对象类型使用
4.实现equals()
在Object中实现的缺省equals()是在判断引用等价性 <—重写
错误的示例:
?是overload,不是override
正确的示例:
先用instanceof判断类型,再调用私有的辅助函数判断等价性
<在没有AF的前提下无脑判断每个域是否相同不可取>
关于instanceof
用于判断一个对象是否是某一特定类型,动态检查
除了实现equals()方法之外,最好不要使用
5.equals()规约
(1)满足等价关系
(2)一致性:多次调用equals应返回相同结果,除非对象被修改
(3)x!=null?x.equals(null)==false
(4)相等对象的hashCode()结果必须一致(除非你能保证该类的对象不会被加入到某种哈希结构中)?equals()和hashCode()必须同时重写
6.可变类型的等价性
观察等价性:不改变状态的情况下,两个mutable对象是否看起来一致(通过调用除mutators外的方法)?比较常用
行为等价性:调用对象的任何方法都展示一致的结果(通过调用任何方法)
在JDK中,不同的 mutable类使用不同的等价性标准
<对immutable对象来说,观察等价性和行为等价性是等价的,因为没有mutator>
如果mutable的对象在集合类中:
当其发生改变后,集合类的行为不确定!
例:
List<String> list = new ArrayList<>();
list.add("a");
Set<List<String>> set = new HashSet<List<String>>();
set.add(list);
set.contains(list)→true
list.add("goodbye");
set.contains(list)→false
原因:向list添加元素后,list的hashCode()改变了