基类不定义等于但子类需要。如何实施?

时间:2011-02-17 20:30:29

标签: java methods equals hashcode

我无权访问基类代码。但是需要能够在子类中定义equals,同时考虑一些基类属性。

此外,基类没有受保护的字段。所有字段只能通过访问者/变更器访问。

仅仅对子类等于的基类字段进行比较会被认为是不好的吗?为什么?

我需要这样做,因为我的基类有一个默认等于不能用于我的目的,但它也有一些字段需要在做一个子类等于...时考虑...

4 个答案:

答案 0 :(得分:6)

是的,你可以这样做,在你的超类中调用getter是没有任何问题的,因为你可以按照你想要的方式确定相等,只要你遵守合同:

  

Reflexive :x.equals(x)应该返回true。

     

对称:x.equals(y)== y.equals(x)

     

传递:x.equals(y)&& y.equals(z)=> x.equals(z)的

     

一致:除非x或y在调用之间发生变异,否则x.equals(y)的多次调用始终返回true或false。

equals-hashcode合约:

  

Equal对象必须具有相同的哈希码

http://download.oracle.com/javase/6/docs/api/java/lang/Object.html#equals(java.lang.Object)

答案 1 :(得分:2)

这是完全合理的。在对派生类进行比较时,考虑从基类继承的属性没有任何问题。基本上,当您比较两个对象时,重要的是它们是否与您选择的某个定义相同,无论该比较的信息来自何处。使用你需要的任何东西。

答案 2 :(得分:0)

如果您还覆盖hashCode(),并且提供的相关属性不可变,则应该没有问题。

equals()方法有时会返回true,有时会返回false,具体取决于某人是否同时调用了setXXX(),这是一件非常危险的事情 - 它不能用得太多equals()的好处,例如确定集合中的成员资格。

如果equals()确实是您所需要的 - 为了使用其他API,例如java.util.Collections - 那么我建议覆盖mutator抛出UnsupportedOperationException。如果没有,您的equals()方法将不可靠。例如,请参阅:How to use two numbers as a Map key

如果你不能 - 例如如果mutators是final - 那么我甚至不会尝试子类化。相反,我将'superclass'对象中的值复制到我自己的字段中,然后将原始文件丢弃。 (如果你保留它,即使是私有字段,你也不能指望别人没有引用它并改变它。)如果你需要你的'子类'与需要'superclass'的API互操作,然后包含一个asXXX()方法,可以动态生成“超类”对象。

否则,如果您只是需要根据自己的目的确定等效性,我根本不会覆盖equals() / hashCode(),而是创建一个新方法,并将其称为{{{ 1}}。

答案 3 :(得分:0)

覆盖等于没有什么特别的错误,如果你需要这样做,那么通过getter访问私有方法肯定没有错。

然而,这里有一个轻微的概念问题,与Liskov Substitution原则有关,该原则指出你应该能够用子类代替基类而不能对行为进行任何概念上的改变。

如果你实现的equals()概念与基类中实现的equals非常不同,那么使用你的代码的人(比如维护者)会发现很难理解。他们将根据某些假设进行编码,这些假设将被证明是错误的。例如,如果base equals()基于引用相等,即

equals(Object o) { return this == o;}

并且您的实现做了一些非常不同的事情,用户需要了解更多有关具体实现的信息。它也会违反对称性:如果x是你的子类而y是基类,x.equals(y)将不会与y.equals(x)相同。

据说这些都不是不可克服的,如果你不能修改基础,你可能没有选择。为你的班级添加很多评论。