Rob Spoor wrote:. . . if you add a field . . .
If you simply add a field, equals()
will still fulfil their general contract, even though you will now have a peculiar definition of equality.
See line 5.
You can now have two cars with the same make and number but travelling at different speeds and neither equals()
will notice a difference. Strange, but it is a conceivable situation in real life, particularly amongst the criminal classes
Your troubles will start if you update equals()
but not both; I think updating only hashCode()
will break equals()
but not vice versa
Another way to break those methods with an additional field is to add that field in a subclass.
Round here, it is legal for taxis to be registered in several boroughs, so the charge can differ on where the fare is picked up. If you use the charge in Taxi#hashCode()
only, goodbye general contract for hashCode()
. And if you use it in equals()
, you have the same problem as Point/ColoredPoint (Joshua Bloch: described in Effective Java
, and I think Angelika Langer uses the same example). Goodbye transitivity, and probably goodbye symmetry. Whether a tool will generate such a method, I don't know.
I am sure Rob is correct that generated code will be correct and doesn't need testing. But if such a method is generated in subtypes, then the generated code can be incorrect. If your tool generates an equals()
method in Car and in Taxi, even if you remove chargePerMile
from the method, you will still have incorrect code because one version will include ...ob instanceof Car...
and the other ...ob instanceof Taxi...
Goodbye symmetry. Some of the errors you get in handwritten code only can be avoided with @Override
. But do any of your tests compare hash codes?