Object-Oriented Coding Standards – Should Equality Be Commutative Within a Class Hierarchy?

coding-standardsmathobject-oriented

It is easy to define the Equals operation in ways that are not commutative. When providing equality against other types, there are obviously situations (in most languages) were equality not being commutative is unavoidable. However, within one's own inheritance hierarchy where the root base class defines an equality member, a programmer has more control.

Thus you can create situations where

(A = B) ≠ (B = A), where A and B both derive from base class T

Substituting the = with the appropriate variation for a given language. (.Equals(_), ==, etc.)

That seems wrong to me, however, I recognize I may be biased by background in Mathematics. I have not been in programming long enough to know what is standard/accepted/preferred practice when programming.

Do most programmers just accept .Equals(_)may not be commutative and code defensibly. Do they expect commutativity and get annoyed if it is not. In short, when working in a class hierarchy, should effort me made to ensure Equality is commutative?

Best Answer

Non-symmetric1 equals breaks the contract of the operation, spelled out clearly in the documentation (I'm quoting from the Java's documentation, but it remains essentially the same in other languages)

The equals method implements an equivalence relation on non-null object references:

  • It is reflexive: for any non-null reference value x, x.equals(x) should return true.
  • It is symmetric: for any non-null reference values x and y, x.equals(y) should return true if and only if y.equals(x) returns true.
  • It is transitive: for any non-null reference values x, y, and z, if x.equals(y) returns true and y.equals(z) returns true, then x.equals(z) should return true.
  • It is consistent: for any non-null reference values x and y, multiple invocations of x.equals(y) consistently return true or consistently return false, provided no information used in equals comparisons on the objects is modified.
  • For any non-null reference value x, x.equals(null) should return false.

These are mathematical properties a relation must have in order to be called an equality relation. A relation can be defined without any of these properties2, but fundamentally it is not an equality relation, and it is dangerous to use it in the context where the equality relation is implied.


1 The right term in the context of equality is "symmetric", not "commutative".

2 For example, it is very tempting to define equality of floats as "two numbers with the absolute difference less than a small epsilon"; that's a very bad idea, because it breaks transitivity.

Related Topic