# Cleanly overridable/modifiable compareTo() method?

Having scoured the web and found little helpful information regarding the implementation of an overridable compareTo() method, I determined myself to find a solution. In another thread I was pointed to some information pertaining to an overridable equals() method, however compareTo() has some pretty unique issues which must be overcome (namely, how to deal with objects of a related supertype, but each existing in a separate hierarchical branch). I've considered many possible scenarios and believe that I've implemented a type which allows for the modification of relational behavior by subtypes, however I'd like external verification that I'm not breaking the compareTo() contract.

public abstract class RelationalObject
implements Comparable<RelationalObject>
{
/*
* Compares two RelationalObjects for semantic ordering.
*
* @param other The RelationalObject to be compared.
*
* @return An int value representing the semantic relationship between the
*         two RelationalObjects. A value of 0 is returned if the two
*         objects are determined to be equal. A negative value is
*         returned if "this" object is determined to have a
*         lower semantic ordering than the "other" object. A positive
*         value is returned if "this" object is determined to have a
*         highter semantic ordering than the "other" object.
*/
public final int compareTo(RelationalObject other)
throws ClassCastException, NullPointerException
{
if (other == null)
throw new NullPointerException("other: Cannot be null.");

int relation = 0;

if (!this.equals(other))
{
if (this.getClass().isAssignableFrom(other.getClass()))
{
if (this.getClass() == other.getClass())
relation = this.compareToExactType(other);
else
/*
* Defer comparison to subtype, thereby allowing an
* optional override of compareToSuperType().
*/
relation = -1 * other.compareTo(this);
}
else
{
if (other.getClass().isInstance(this))
relation = this.compareToSuperType(other);
else
relation = this.compareToForeignType(other);
}
}

return relation;
}

/*
* Compares two RelationalObjects with the exact same class type for
* semantic ordering. The comparison may be based upon any of the class
* state elements so long as the compareTo() method contract is not
* broken.
*
* @param exact The RelationalObject with exactly matching type to be
*              compared.
*
* @return An int value representing the semantic relationship between the
*         two RelationalObjects.
*/
protected abstract int compareToExactType(RelationalObject exact);

/*
* Compares two RelationalObjects not within the same hierarchical branch
* for semantic ordering. The comparison may be based upon only those
* state elements common to both objects (i.e. A comparison must be made
* between each element and the pair's common ancestor). Should the two
* results be equal, a ClassCastException must be thrown as the objects do
* not contain enough distinct information to be further compared.
*
* As only one implementation exists, this should be finalized by the first
* derivative of RelationalObject.
*
* @param foreign The RelationalObject from a foreign hierarchical branch
*                to be compared.
*
* @return An int value representing the semantic relationship between the
*         two RelationalObjects.
*/
protected abstract int compareToForeignType(RelationalObject foreign);

/*
* Compares two RelationalObjects within the same class hierarchical
* branch for semantic ordering. The comparison may be based upon any of
* the class state elements so long as the compareTo() method contract is
* not broken.
*
* @param upper The RelationalObject within the same heirarchical branch
*              and with lesser definition to be compared.
*
* @return An int value representing the semantic relationship between the
*         two RelationalObjects.
*/
protected abstract int compareToSuperType(RelationalObject upper);
}

-

If B and C are subclasses of A (in separate hierarchical branches) they usually should not know about each other even in the compareToExactType method. It leads to tight coupling which we try to avoid in OOP.
Here the other.compareTo(this) and similar calls seems hard to follow, though ones which would not be the easiest to debug, maintain or to figure out what is the order that it provides in a complex case.
I'd try to use a separate Comparator class which knows all the necessary information about A, B, C and the ordering. You may could use something like that was mentioned in my former answer in the Multi-tiered sorting using custom IComparer question.