我是Java编程的导师。我的学生目前被迫(不是我,而是一个不清楚的任务)为一个抽象类实现clone()、equals()和hashCode() 。
为抽象类实现 clone()、equals() 或 hashCode() 有意义吗?你能举一个有意义的例子吗?
我可以想象,当您有抽象类 a 的一些子类 x、y、z 时,这是有道理的。这些子类可能仅在方法的实现上有所不同,因此您不需要将这三个方法实现三次。但我无法想象会出现这种情况的任何情况。
我是Java编程的导师。我的学生目前被迫(不是我,而是一个不清楚的任务)为一个抽象类实现clone()、equals()和hashCode() 。
为抽象类实现 clone()、equals() 或 hashCode() 有意义吗?你能举一个有意义的例子吗?
我可以想象,当您有抽象类 a 的一些子类 x、y、z 时,这是有道理的。这些子类可能仅在方法的实现上有所不同,因此您不需要将这三个方法实现三次。但我无法想象会出现这种情况的任何情况。
我不会实施clone().
equals()但是实现,hashCode()并toString()为所有子类提供默认行为是有意义的。如果孩子没有添加新的班级成员或根据需要补充,他们可以选择使用它。
误读了你的问题,并认为你也问过toString- 同样的推理仍然适用
例如,基本上迭代集合并以用户友好的方式打印它的实现AbstractCollection。toString()
直接子类:
AbstractList, AbstractQueue, AbstractSet, ArrayDeque, ConcurrentLinkedDeque
所以所有集合、列表和队列都共享该toString方法。如果需要,每个子类都可以自由地重新实现它。
作为另一个示例,equals实现低一级(在 AbstracList/Set 等中)。
另一方面,clone是在最终实现中实现(例如 ArrayList),而不是在抽象类中。
底线:有时它是有意义的,但有时它没有,它可能不应该是适用于所有情况的义务。
1)clone()方法非常有用,当你需要实现某种对象的深度复制,同时你不能只使用对这个对象的引用,而是需要它们的新实例。所以,重写这个方法是有意义的。
2)equals()并且hashCode是两个重要的方法,当您需要特殊行为时必须重写HashSet/HashMap它们,其功能取决于这些方法的实现。因此,覆盖它们也是有道理的。
一个主要问题clone()是有两种实现方式,派生类中的正确实现取决于其父类的功能。
如果父类及其所有祖先调用super.clone()直到调用到达object.clone(),那么派生类要做的正确的事情是调用super.clone然后替换任何封装目标对象的可变状态而不是它们的身份的“添加”成员,用封装相同状态的新对象。如果派生类不包含任何封装可变对象状态的附加成员,则派生类不需要做任何事情,clone而可以简单地使用父类的实现。
实现类的另一种方法clone()是让它包含一个构造函数,该构造函数接受其自己类型的参数,并链接到父构造函数,该构造函数同样执行此操作,然后将所有适当的属性“新”复制到类型中传入实例到新实例。这种方法的一个优点是即使基类以clone这种方式实现它也可以工作。然而,这种方法有两个缺点:
clone()通过调用来实现,super.clone()但有一个祖先没有,那么生成的对象最终将是父类型而不是派生类型——不是clone()应该采取的方式。
方法 clone()、equals() 和 hasCode() 通常必须在实现该抽象类的类中实现,因为它们需要抽象类中不存在的字段。
然而,在某些情况下,equals()、hascode() 和可能的 clone() 在抽象类中实现是有意义的。(例如,equals() 在抽象容器类中有意义,例如 Collections 等)
对于 hashCode() 和 clone() 我更怀疑这是否有意义。
能说得通吗?
clone()是有意义的。clone()equals()并hashCode()有意义。该契约可以由它自己指定,也可以由它实现的超类或接口指定。它是否合适,即我们是否想要设计一个抽象超类来覆盖这些?
clone()机制本身很少适用。一种适当的实现可能是显式地抛出 aCloneNotSupportedException并生成它final,并以这种方式防止子类实现Cloneable。equals()和hashCode()明智的情况也是适当的情况。如果一个抽象超类本身可以满足平等契约规范,它应该这样做。并且它应该制定equals()和hashCode()方法final,以防止LSP违规。我会引用 Josh Bloch 的话:没有办法在保留 equals 契约的同时扩展一个可实例化的类并添加一个值组件——Effective Java 2nd ed。