Equals vs the Encapsulation Boundary
If we make the assumption that Object encapsulation is preferred we end up in a slight conundrum... Java's Object class provides an over-ridable method 'equals(...)' in which the current object compares itself with a provided object for equality and/or equivalence. We assume an ideal language.
What is equality?
Equality/equivalence (they are slightly different) can fall into two distinct categories:
- Two objects are 'equal' if they are the same object. (Equality)
- Two objects are 'equal' if certain properties of each object have the same values. (Equivalence)
What is the problem?
In Java, two classes can be compared if they are equivalent by comparing the relevant data fields in each class. This breaks object encapsulation if you want to compare normally inaccessible fields.
How can we solve this?
Various options exist:
- We can decide that object encapsulation is bad (or rather that class encapsulation is the better of two evils).
- We can decide that object encapsulation is good, but provide an exception.
- We can decide that object encapsulation is good.
If object encapsulation is good:
- The obvious solution is to add public getters for all the fields that need to be examined and use them from the equals method. However, this breaks many heuristics such as Avoid interface pollution, Beware of many accessors, Minimize number of methods and Hide data within its class.
- We can provide a subclass-able Comparator class that can provide comparisons of equality between two provided objects of a class. This means that any fields that need to be compared need to be made accessible, probably in the form of getters. An analogy... Two people stand beside each other, in order to determine the relative straightness of their teeth, either, one needs to look at the other and also have a mirror, or someone has to look at both of their teeth for them. This has the same problem as above.
- Other solutions?
Is this a more general problem?
Is this a more general problem with object encapsulation? Is it not a problem at all?
- Stephen would argue that this is a general problem with object encapsulation. Other groups of methods will have the same problem.
- Matthew would argue that this is not a problem at all. If objects want to compare themselves then the type of information they want to compare is stuff that should be available anyway.
- Michal thinks that surely if you can't see stuff, why would you care about it anyway when talking about equivalence? Also, shouldn't this be on the talk page?
- Wal would argue that you shouldn't need equals() in the first place most of the time because you should generally only have unique objects in the first place. See Avoid equals.
- Why yes. Yes, he would. He's also mention that you can use Tell, don't ask for equals on those rare occasions when you need it.
A Possible Example
We have a pseudo-random number generator. The class is implemented with an algorithm using a seed and a location in the sequence. It provides the methods 'currentRanNum()' & 'nextRanNum()'. Assuming we want to compare equivalence of two of these objects, we don't want to just compare the current random number as the objects may appear to be equivalent while actally having completely different seeds or even having the same seed and being at different positions in the sequence. We infact need to look at the current number, the seed and the location in the sequence to discover if they are actually equivalent. This would require exposing the seed and the location in some way.