3

Given an interface I:

interface I<T> {
    public abstract T doSomthing(T other);
}

where any class C which implements the interface I will always use itself (C) as the type parameter:

class MyClass implements I<MyClass> {

    @Override
    public MyClass doSomthing(MyClass other) {
        return null;
    }
}

Is there a way to accomplish this without explicitly passing the class C as the parameter every time a new class implements the interface?

In other words is it possible, in an interface, to reference the class which implements that interface?

Lucas Burns
  • 393
  • 1
  • 3
  • 14
  • Is there any language that actually does that? It's verbose for a reason (mostly because it'd create a mess during inheritance) – Pawel Mar 30 '21 at 19:44

3 Answers3

2

tl;dr

You asked:

Is there a way to accomplish this without explicitly passing the class C

No, not in Java.

Example

You seem to be describing exactly the scenario of the Comparable<T> interface bundled with Java. That interface has a single generic argument, for the type of the two objects to be compared. That interface requires a single method compareTo​(T o) taking a single parameter of that same generic type.

Let’s look at an example usage in the OpenJDK source code, the source code for class Year.

The class declares itself explicitly as the type of comparison on the Comparable interface being implemented.

public final class Year
        implements Temporal, TemporalAdjuster, Comparable<Year>, Serializable {

The compareTo method explicitly cites its own class as the type being compared.

@Override
    public int compareTo(Year other) {
        return year - other.year;
    }

You asked:

Is there a way to accomplish this without explicitly passing the class C as the parameter every time a new class implements the interface?

It seems the answer is No. The implementing class must cite itself explicitly as the fulfillment of the generic type of the interface being implemented.

Caveat: (a) I am not an expert on such language matters. (b) I may have misunderstood your question.

Basil Bourque
  • 303,325
  • 100
  • 852
  • 1,154
2

To add to the other answer: what you're describing is a self type.

Some other languages have it (such as Scala).

But I'm afraid Kotlin doesn't.  (Java doesn't, either.)

There has been long discussion about the possibility of adding it to a future version of Kotlin; it seems the potential uses may not be wide enough for it to be worthwhile, though there doesn't seem to be a final consensus.

The usual workaround is using a type parameter — similar to what C++ calls the curiously-recurring template pattern.  It's not quite as typesafe in Java or Kotlin, as this question illustrates, but covers most of the same ground.

gidds
  • 16,558
  • 2
  • 19
  • 26
1

That's called self-bounded generics. It could be declared in Java as well as in Kotlin.

Java:

interface I<T extends I<T>> {
    public abstract T doSomething(T other);
}

Kotlin:

interface I<T : I<T>> {
    fun doSomething(other: T): T
}

But it doesn't mean, that generic parameter could be omitted then you declare classes, implementing this interface. It just imposes additional restrictions on type, you're passing as a generic parameter (narrowing it down to only one type). Type inference is not supported for class declaration neither in Kotlin, nor in Java.

Also see: Can I resolve a generic type from another generic declaration in an interface?