Search code examples
javainheritanceinterfaceabstractcomparable

Abstract Inheriting form of Comparable Interface


I understand how to use the Comparable<T> interface, but in this specific example, I'm wondering if there is a way to require the inheriting Class from an Abstract Class (which implements the Comparable<T> interface) to be Comparable against itself.

Let me reiterate, there is an Abstract Class that implements the Comparable Interface:

public abstract class MyAbstractClass implements Comparable<MyAbstractClass>

And a Class which inherits from this Abstract Class:

public class MyClass extends MyAbstractClass

Typically with this setup, the following method is required to satisfy the Comparable Interface:

public int compareTo(MyAbstractClass otherAbstractObject)

This requires me to make the following cast:

public int compareTo(MyAbstractClass otherAbstractObject)
{
    MyClass otherObject = (MyClass) otherAbstractObject;

    // Comparison...
    return result;
}

Given the fact that this cast could easily fail by trying to use a different child of MyAbstractClass, I would like to be able to define my Abstract Class to accept the following method:

public int compareTo(MyClass otherMyObject)
{
    // Comparison...
    return result;
}

And ideas on how to accomplish this? Or is it simply not possible?


Solution

  • You can define MyAbstractClass using generics as follows:

    public abstract class MyAbstractClass<T extends MyAbstractClass<T>>
        implements Comparable<T> {
    

    Then you can define subclasses such as

    public class MyClass extends MyAbstractClass<MyClass>
    

    which allow you to define the compareTo method like this:

    public int compareTo(MyClass otherMyClass)
    

    However, that doesn't prevent anyone from writing a subclass that doesn't conform to the pattern:

    public class SneakyClass extends MyAbstractClass<MyClass>
    

    which would also define the compareTo method similarly:

    public int compareTo(MyClass otherMyClass)
    

    Note: There's nothing that can force the generic type parameter of a class to equal the class on which it's defined; the best you can do is to enforce an upper bound on the abstract class, to at least force it to be some kind of MyAbstractClass.