Search code examples
javainheritancecomparable

Stuck with Java interface Comparable, generics and inheritance


Ok, this is my problem simplified:

class Group<T extends Comparable<T>> implements Comparable<Group<T>> {
    private String id;

    public Group(String id) {
        this.id = id;
    }

    @Override
    public int compareTo(Group<T> o) {
        return id.compareTo(o.id);
    }
}

class InnerGroup extends Group<Integer> {
    public InnerGroup(String id) {
        super(id);
    }
}

class OuterGroup extends Group<InnerGroup> {
    public OuterGroup(String id) {
        super(id);
    }
}

This produces this error by the compiler:

Error:(20, 32) java: type argument InnerGroup is not within bounds of type-variable T

In reference to OuterGroup trying to extend Group. ItelliJ Idea says it's because InnerGroup must implement Comparable, but it is already doing so by means of inheriting it from Group.

In fact, if I try to force InnerGroup to implement Comparable, then the compiler will complain because InnerGroup would have two implementations of Comparable, which is an implicit recognition that it already has the interface implemented despite the aforementioned complain of not having it.

Any ideas on how to get out of this conundrum?

Thanks a lot in advance.


Solution

  • I think I've managed to solve this once and for all. The solution of @shmosel had some side effects when things got a bit more complex, and once I have managed to fully grasp it, I think it didn't express what I wanted precisely. This, however, should do it:

    class Group<T extends Group<T, R>, R extends Comparable<R>> implements Comparable<T> {
        String id;
    
        public Group(String id) {
            this.id = id;
        }
    
        @Override
        public int compareTo(T o) {
            return id.compareTo(o.id);
        }
    }
    
    class InnerGroup extends Group<InnerGroup, Integer> {
        public InnerGroup(String id) {
            super(id);
        }
    }
    
    class OuterGroup extends Group<OuterGroup, InnerGroup> {
        public OuterGroup(String id) {
            super(id);
        }
    }