Plargato
Plargato

Reputation: 555

How can i make an interface in java with a function that accepts a parameter of the type that extends the interface?

How can i make an interface in java with a function that accepts a parameter of the type that extends the interface?

For example take the interface ISelfComparable

if class A extends it then i would expect it to implement

bool compareTo(A other)

but if class B extends it then i would expect it to implement

bool compareTo(B other)

I know i can use a generic interface but it seems incorrect because it doesn't make any sense for A to extend ISelfComparable<B>

If this is impossible, what is the best practice in this kind of situation?

Upvotes: 1

Views: 76

Answers (3)

biziclop
biziclop

Reputation: 49794

The usual solution is self-bounded generics, as seen in the Enum class.

interface Example<T extends Example<T>> {
    void foo(T t);
}

public class ExampleImpl implements Example<ExampleImpl> {
    @Override
    public void foo(ExampleImpl example) {
    }
}

How it works is a bit dizzying, but is explained very well here for example. There is also a very good answer on the subject here.

Note that it isn't foolproof, as it allows this:

public class ExampleImpl2 extends Example<ExampleImpl {
    @Override
    public void foo(ExampleImpl example) {

    }
}

But in practice the self-bounded idiom is used to express exactly the sort of thing you're after.

If you really, really, really need the parameter object to always be the exact same class as this, you have to do a runtime check. (It also raises the question of why you need this, but that would take us way off topic.)

Upvotes: 2

Ruslan
Ruslan

Reputation: 6300

There is a way to check the type of parameter but only in runtime. For example you can implement type checking in default method:

interface ISelfComparable {
    default boolean compareTo(ISelfComparable param) {
        if (this.getClass() != param.getClass()) {
            throw new IllegalArgumentException();
        }
        ...
    }
}

Then each implementation of this interface should look like this:

class A implements ISelfComparable {
    @Override
    public  boolean compareTo(ISelfComparable param) {
        ISelfComparable.super.compareTo(param);
        ...
    }
}

In this case if you call new A().compareTo(new B()); then java.lang.IllegalArgumentException will be thrown

Upvotes: 0

Maurice Perry
Maurice Perry

Reputation: 9648

Have a look at the class java.lang.Comparable: it has an argument with the type of the objects that can be used int compareTo.

By analogy:

public interface ISelfComparable<T extends ISelfComparable<T>> {
    boolean compareTo(T other);
}

Upvotes: 0

Related Questions