Is there a specific rule on how Overriding equals()
& hashCode()
in sub classes considering super fields ?? k
Generally speaking implementing equals across subclasses is hard to keep symmetric and transitive.
Consider a superclass that checks for field x
and y
, and subclass checks for x
, y
and z
.
So a Subclass == Superclass == Subclass where z is different between the first instance of Subclass and the second, violating the transitive part of the contract.
This why the typical implementation of equals will check for getClass() != obj.getClass()
instead of doing an instanceof. In the above example, if SubClass or Superclass does an instanceof check it would break symmetry.
So the upshot is that a subclass can certainly take into account super.equals() but should also do its own getClass() check to avoid the above issues and then check for equals on its own fields in addition. It would be a strange duck of a class that changed its own equals behavior based on specific fields of the superclass rather than just if the superclass returns equals.
Children should not examine the private members of their parents
But obviously, all significant fields should be taken into account for equality and hashing.
Fortunately, you you can easily satisfy both rules.
Assuming you're not stuck using the NetBeans-generated equals and hashcode, you can modify Hominidae's equals method to use instanceof comparison rather than class equality, and then use it straightforwardly. Something like this:
@Override
public boolean equals(Object obj) {
if (obj == null) { return false; }
if (getClass() != obj.getClass()) { return false; }
if (! super.equals(obj)) return false;
else {
// compare subclass fields
}
Of course, hashcode is easy:
@Override
public int hashCode() {
int hash = super.hashCode();
hash = 89 * hash + (this.name != null ? this.name.hashCode() : 0);
hash = 89 * hash + (this.faceBookNickname != null ? this.faceBookNickname.hashCode() : 0);
return hash;
}
Seriously, though: what's up with NetBeans not taking superclass fields into account by calling the superclass methods?
Because inheritance breaks encapsulation, subclasses that implement equals() and hashCode() must, necessarily, account for the peculiarities of their superclasses. I've had success encoding calls to the parent class's equals() and hashCode() methods from the subclass's methods.
I prefer to use EqualsBuilder (and HashcodeBuilder) from the commons-lang package to make my equals() and hashcode() methods a lot easier to read.
Example:
public boolean equals(Object obj) {
if (obj == null) { return false; }
if (obj == this) { return true; }
if (obj.getClass() != getClass()) {
return false;
}
MyClass rhs = (MyClass) obj;
return new EqualsBuilder()
.appendSuper(super.equals(obj))
.append(field1, rhs.field1)
.append(field2, rhs.field2)
.append(field3, rhs.field3)
.isEquals();
}
Regarding the accepted @CPerkins answer, I don't think the given equals() code will work reliably, due to the likelihood that the super.equals() method will also check for class equality. A subclass & superclass will not have equal classes.
It sounds like your parent (super) class doesn't override equals. If this is the case then you need to compare the fields from the parent class when you override this method in the sub-class. I agree that using the commons EqualsBuiler is the way to go but you do need to be careful that you don't break the symmetry/transative portions of the equals contract.
If your sub-class adds attributes to the parent class and the parent class isn't abstract and overrides equals you're going to get in to trouble. In this scenario you should really look at object composition instead of inheritance.
I'd strongly recommend the section in Effective Java by Joshua Block on this. It's comprehensive and really well explained.