Reputation: 3535
I have a superclass with 2 variables (int a
) (int b
) and have a subclass, which extends the functionality of the superclass by overriding 2 superclass methods with improved methods now in the subclass. As part of my subclass I now have a new int
(int c
) which is a unique id (UUID).
I understand equality is difficult to maintain with the equals
method
Can I override the Superclass equals
and hashCode
methods to show equality AND also do the same for the subclass equals
and hashCode
method based on my situation described above?
I had initially overriden the equals
and hashCode
methods in the superclass. If it supposed to be done for the subclass also because of the extra Instance Variable (int c
) in the subclass. I understand that there should be a hashCode
method to show this, and I read if the haschCode
is changed then the equals
method of the subclass has to change?
I am really getting confused as to what best to do.
I was wondering if my superclass equals
and hashCode
methods can show the equality relationships? Is it allowed in conjunction with my superclass equals
and hashCode
overriden methods that the subclass can show equals comparison for int a
, int b
and int c
and the hashCode
methods of the subclass updated to show a unique hashcode for int
s a
, b
and c
?
I was thinking of comparing my int
s a
and b
in the superclass equals
method and update hashcode for these 2 variables and int
s a
, b
and c
in the equals
method, updating hashcode for these 3 variable. It's just that int c
in the superclass is unique?
Very grateful for any advice here as I believe ignoring and not dealing with the int c
in the subclass equals
and hashCode
methods may be a no no.
Thanks in advance
Upvotes: 2
Views: 2089
Reputation: 1297
It depends. Lets say your super class is A
and B extends A
then this can occur
a.equals(a)
b.equals(b)
a.equals(b)
(true)? b.hash == a.hash : hash doesn't matterb.equals(a)
(true)? b.hash == a.hash : hash doesn't matterHow should be A
and B
related? There are two options:
A
and B
are completely different, therefore a.equals(b)
or b.equals(a)
is always false. This is the most safe way. You need in equals to test a.getClass() == b.getClass();
to ensure a
and b
is exactly same type. For example Eclipse IDE generates this kind of equality automatically by default in generate equals() and hashCode().A
and B
can be compared, but you can't override it in B
to keep contract of equals()
and hashCode().
This is forced due symmetric contract (a.equals(b) == b.equals(a)
) of equals.Upvotes: 0
Reputation: 1932
++ to Jordan Bently.
It is generally a good idea to override equals()
, toString()
, and hashCode()
for each class you write. In practice it does not always make sense. But for what you are doing, I would do so. And yes, you can change the implementation in the subclass.
It is good to mark each of your overriden methods with @Override
to help provide documentation to the developer(s) that you are overriding. This clues them that you are at least overriding java.lang.Object
, if not your super class as well.
Upvotes: 0
Reputation: 1398
In order to determine the behavior of hashCode and equals, you need to consider a few scenarios.
class Foo { int a, b; }
class Bar extends Foo { int c;}
Are a Foo and Bar with the same a and b values equal (i.e., do they represent the same value)? If so, then add the equals and hashCode implementation to Foo, and don't override it in Bar. In equals, make sure to check that the object is instanceOf Foo, not that the classes are equal.
Are Bar instances with different c's equal? If so, then don't override Foo's implementation of hashCode and equals.
Otherwise, you should have an implementation of equals and hashCode in both Foo and Bar. Make sure to design it so that Foo instances are only equal to other Foo instances, and Bar instances are only equal to other Bar instances. If not, you could easily violate the symmetry required by equals, e.g
Foo x = new Foo(a,b);
Bar y = new Bar(a,b,c);
x.equals(y); //returns false
y.equals(x); //returns true
The above is very bad, and will cause strange behavior, if for example you put a Foo and a Bar into a Set.
Finally, you should NOT write your own implementation of hashCode and equals for these objects. Most IDEs have an auto-generation tool for these, use that instead.
Upvotes: 0
Reputation: 269797
The crux of your question is whether you want it to be possible for an instance of your superclass and an instance of your subclass to compare as equal.
If so, don't override the equals()
and hashCode()
methods. You might even make them final
in the superclass.
If not, then the equals()
method of each class should check the type of the argument to equals()
using getClass()
, not instanceof
. For example, in the superclass:
if ((obj == null) || (!getClass().equals(obj.getClass()))
return false;
/* Compare a and b. */
...
In the subclass:
if (!super.equals(obj))
return false;
/* Compare c. */
...
If the hash code is based on the a
and b
fields, you probably won't have to override the hashCode()
method, but your class will probably work better as a key if you do account for c
in the subclass' implementation. That is, it will put keys with different values of c
into different buckets, rather than clumping all instances with the same a
and b
in the same hash bucket.
Upvotes: 1
Reputation: 242716
Basically, you have two possible options:
Ignore c
altogether. Define equality for superclass in terms of a
and b
and don't override it in subclasses.
Always treat instances of superclass and subclass as not equal. It allows you to define equality differently in superclass (based on a
and b
) and subclass (based on a
, b
and c
).
Note that overriding equals()
and hashcode
in subclass is not enough in this case - you also need a special trick when implementing equals()
method of superclass, see part about canEquals()
method in How to Write an Equality Method in Java.
Upvotes: 1