2
votes

I have a superclass with 2 instance variables (say int a, and int b) and have now decided I need to have one instance variable in my subclass int c.

I had overriden the superclass equals and hashCode method to take into account equality of objects/values. I have also overriden the superclass toString to give a string representing the state of the objects (variable values).

Based on the above and the fact I now have a single instance variable int c in my subclass I was wondering if I

  1. need to override the toString method in the subclass or is this a no no as I have a valid inheritable toString method (already overriden) in the superclass that can be used for the subclass string representation?
  2. need to override the equals method in the subclass. Can this be done by calling the superclass equals method and adding the comparison code for my subclass instance variable after the call, or does it require a new implementation? I figure the latter?
  3. I was going to override the hashCode method in the subclass. Again is it best to have a new implementation than call the superclass hashCode method? I was going to compare a, b and c in the subclass equals method with another object and also create hash codes for a b and c in the subclass hashCode method? Is this the way to go or does it require me to only consider variable c in the subclass equals and hashcode methods?

I have had a look at various resources including Effective Java by bloch (chapter 3) but could not find the answer to the above questions that I have

4

4 Answers

4
votes

This answer assumes your class look like this:

public class MySuperClass {
    int a,b;
}

public class MySubClass extends MySuperClass {
    int b;
}

Firstly, your comments re toString() are irrelevant to the main questions. In any case, your code should never rely on the toString implementation - its output for humans only. Feel free however to use super impl:

public String toString() {
    return super.toString() + ", c=" + c;
}

Secondly, equals() should compare the (published) state of your objects. Since the subclass has another field, it will need its own equals(). However, you may be able to use the equals() method of the super class, like this:

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;
}

Thirdly, hashcode should align with equals, so implement it too. Again, you can use super's impl that hashes up a and b:

public int hashcode() {
    return super.hashcode() + new Integer(c).hashCode(); // for example
}
2
votes

As long as everything in the subclass exists in the superclass, there is no need to override them (unless, of course, you want some different functionality).

Basically, only override the method if you want different functionality for each subclass.

But of course, you said that your subclass has a new variable, int c. In this case you would need to override the method to have complete functionality, especially for equals() and hashCode().

0
votes

It depends on what you're trying to represent, and what your equals and hashCode methods currently do. You don't strictly need to override unless you want the new fields added by the subclass to be taken into account, or if your superclass methods are not robust to the possibility of the class being extended (e.g., comparing obj.getClass() instead of using instanceof).

0
votes

If you want to correctly represent the hash of the object, then you need to override both equals and hashCode. If you do not override hashCode() then objects that vary only by a difference in your new field c will all be put into the same hash bucket (and if you override hashCode then you must override equals since two equal objects must have the same hash). Your implementation of hashCode can make use of the super classes implementation and add it to the additional subclass fields.

Unfortunately, it is impossible to write a strictly correct equals function for a class that subclasses a non-abstract class and adds a new field to it. You will either end up breaking some of the contractual properties of equals or making sub classes that only add methods also end up being unequal.

The recommended way around this is to not subclass in order to add fields, but instead to make a composite class that includes an instance of the would be parent class as well as the new fields, and also exports a view of the included class so it can be compared if needed.