我有一个包含2个实例变量的超类(比如int a
和int b
)和
现在已经决定我需要在我的子类int c
中有一个实例变量。
我已经覆盖了要考虑的超类equals和hashCode方法 对象/值的相等性。我还覆盖了超类toString来给出一个字符串 表示对象的状态(变量值)。
基于以上和事实,我现在在我的子类中有一个实例变量int c 我想知道我是否
我已经看过各种资源,包括bloch的Effective Java(第3章),但找不到上述问题的答案
答案 0 :(得分:3)
这个答案假设你的班级看起来像这样:
public class MySuperClass {
int a,b;
}
public class MySubClass extends MySuperClass {
int b;
}
首先,您的评论toString()
与主要问题无关。在任何情况下,您的代码都不应该依赖于toString实现 - 它仅为人类输出。但是请随意使用super impl:
public String toString() {
return super.toString() + ", c=" + c;
}
其次,equals()
应该比较对象的(已发布)状态。由于子类有另一个字段,因此它需要自己的equals()
。但是,您可以使用超类的equals()
方法,如下所示:
public boolean equals(Object o) {
// The super equals() will compare int a and int b for us
if (!super.equals(o)) {
return false;
}
// super thinks it is equal, so let's compare int c
return o instanceof MySubClass && ((MySubClass)o).c == c;
}
第三,hashcode
应该与equals对齐,所以也要实现它。同样,你可以使用super的impl来加剧a和b:
public int hashcode() {
return super.hashcode() + new Integer(c).hashCode(); // for example
}
答案 1 :(得分:1)
只要子类中的所有内容都存在于超类中,就不需要覆盖它们(当然,除非你想要一些不同的功能)。
基本上,如果您希望每个子类具有不同的功能,则只覆盖该方法。
但是,当然,你说你的子类有一个新变量int c
。在这种情况下,您需要覆盖该方法以获得完整的功能,尤其是equals()
和hashCode()
。
答案 2 :(得分:0)
这取决于您尝试表示的内容以及您当前equals
和hashCode
方法的用途。除非您希望将子类添加的新字段考虑在内,否则您不需要重写,或如果您的超类方法对于扩展类的可能性不稳定(例如,比较obj.getClass()
而不是使用instanceof
)。
答案 3 :(得分:0)
如果要正确表示对象的哈希值,则需要覆盖equals和hashCode。如果你不覆盖hashCode(),那么只会因新字段 c 中的差异而变化的对象都将被放入相同的哈希桶中(如果你覆盖hashCode,那么你必须覆盖equals,因为两个等于的对象必须具有相同的哈希)。您的hashCode实现可以使用超类实现并将其添加到其他子类字段。
不幸的是,对于一个非抽象类的子类并为其添加新字段的类,不可能编写严格正确的equals函数。你要么最终破坏equals的一些契约属性,要么只使用添加方法的子类也最终不平等。
推荐的解决方法是不要为了添加字段而进行子类化,而是创建一个包含父类的实例和新字段的复合类,并导出包含的视图如果需要,可以对它进行比较。