其他分享
首页 > 其他分享> > 第八章 ADT和OOP中的相等

第八章 ADT和OOP中的相等

作者:互联网

第八章 ADT和OOP中的相等

Reading Sources

Objectives

理解等价关系的性质

站在观察者的角度通过AF理解不可变类型的等价关系

引用等价性和对象等价性的差异

区分可变类型的严格观察等价性和行为等价性

理解Object的契约,正确实现可变和不可变类型的等价关系判定

等价关系

自反 对称 传递

不可变类型的相等

使用AF描述相等

AF映射到同样的结果则等价
f(a) = f(b) --> a和b等价

等价关系引出了抽象函数,抽象函数将每个元素映射到不同的区分类

即由抽象函数引起的关系就是等价关系

使用观察来描述相等

从客户的角度:
使用观察。当两个对象不能通过观察区分时,我们可以说它们是相等的——>即我们可以应用的每个操作都会为两个对象产生相同的结果。

在 ADT 中,“观察”是指对对象调用操作。所以两个对象相等当且仅当它们不能通过调用抽象数据类型的任何操作来区分。

实例

== Vs equals()

==:引用相等

equals(): 对象内容相等

当我们定义一个新的数据类型时,我们有责任决定对象相等对数据类型的值意味着什么,并适当地实现 equals() 操作

比较

对基本数据类型,使用==判定相等

对对象类型,使用equals()
如果用==,是在判断两个对象 身份标识 ID是否相等(指向内存里的同一段空间)

实现equals()

可变类型的相等

在Object中实现的缺省equals()是在判断引用等价性

-->需要重写

注:不是重载
注意下面的问题

有上一章的内容:
要调用的方法的哪个重写版本是在运行时根据对象类型决定的,但是要调用的方法的哪个重载版本是基于编译时传递的参数的引用类型。所以这里实际调用的是Object实现的缺省equals()

-->在重写时为了避免方法签名,应使用 Java 的注解 @Override。使用此注解,Java 编译器将检查超类中是否确实存在具有相同签名的方法,如果您在签名中犯了错误,则会给您一个编译器错误

重写equals()的例子

instanceof

instanceof 运算符测试对象是否是特定类型的实例。

使用 instanceof 是动态类型检查,而不是静态类型检查。

通常,在面向对象编程中使用 instanceof 是a bad smell。除了实现 equals 之外,任何地方都应该禁止它。

此禁令还包括检查对象运行时类型的其他方式。
– 例如,getClass() 也是不允许的。

-->从不在超类中使用 instanceof 来检查子类的类型
如下所示:

使用多态来避免上面的instanceof:

Object契约

重写equals()应该遵循的契约:

Hash Tables

§ 哈希表是如何工作的: – 它包含一个数组,该数组被初始化为与我们期望插入的元素数量相对应的大小。
– 当一个键和一个值出现插入时,我们计算键的哈希码,并将其转换为数组范围内的索引(例如,通过模除法)。然后将该值插入该索引处

哈希表的 rep 不变量包括键值位于由其哈希码确定的槽中的基本约束。

等价的对象必须有相同的hashcode
why:
如果两个相等的对象具有不同的哈希码,它们可能被放置在不同的槽中。
– 因此,如果您尝试使用与插入值相同的键来查找值,则查找可能会失败。

Object 的默认 hashCode() 实现与其默认的 equals() 一致

-->
Always override hashCode() when you override equals() 除非你能保证你的ADT不会被放入到Hash类型的集合类中

可变类型的相等

两种方式:
观察等价性(通过仅调用观察者、生产者和创建者方法。):在不改变状态的情况下,两个mutable对象是否看起来一致

行为等价值性:调用对象的任何方法都展示出一致的结果

注意:
1.对于不可变对象,观察和行为平等是相同的,因为没有任何 mutator 方法。

2.如果某个mutable的对象包含在Set集 合类中,当其发生改变后,集合类的行为不确定,务必小心

如下实例:

原因分析:

教训:
当equals() 和hashCode() 可能受突变影响时,我们可以打破使用该对象作为键的哈希表的rep 不变量。

  1. 在JDK中,不同的 mutable类使用不同的等价性标准…

总结:

clone()

clone() 创建并返回此对象的副本。
“复制”的确切含义可能取决于对象的类别。

自动封装和相等

装箱就是自动将基本数据类型转换为包装器类型;
当把一个基本数据类型的数据赋值给对应的包装器类的时候。
当把一个基本数据类型的数据作为参数传给一个方法,而这个方法想要接收的参数是该基本数据类型对应的包装器类的对象。

拆箱就是 自动将包装器类型转换为基本数据类型。
当把一个包装器类的对象赋值给一个基本数据类型的时候。
当把一个包装器类作为参数传给一个方法,而这个方法想要接收的参数是基本数据类型的时候。

实例

对于上图中的:Numbers between -128 and 127 are true.
原因:

总结

相等是实现抽象数据类型 (ADT) 的一部分。

避免错误

易于理解

随时准备改变

标签:ADT,相等,对象,数据类型,equals,第八章,OOP,哈希,类型
来源: https://www.cnblogs.com/ro2phy/p/16342202.html