0

I have an interface with a function that currently returns itself. However, I would like any implementation classes to instead return that class instead of the base interface. For example, in this simplified example, this works fine:

public interface MyInterface<T, U> {
    public void foo(T t, U u);

    public MyInterface baz();
}

public class MyClass<T, U> implements MyInterface<T, U> {
    @Override
    public void foo(T t, U u) {}

    public MyClass bar() {
        return this;
    }

    @Override
    public MyInterface baz() {
        return this;
    }
}

But if I were to change the last function to this:

@Override
public MyClass baz() {
    return this;
}

This fails, obviously, because the overriding function no longer matches the declaration in the interface.

The reason I need baz() to return Class instead of Interface is because the caller may call bar and baz an arbitrary number of times in an arbitrary order, but currently all bar() calls must be before all baz() calls, unless we repetitively downcast it.

What complicates this even more is the foo() function which uses two generic types. I looked into using curiously recurring generic patterns but was not able to find a reasonable solution because Interface already deals with generics, even without it.

Is there any way around this problem? Thanks!

5
  • Why do you think the overridden baz() can't return Class? Did you try? Commented Aug 12, 2019 at 23:12
  • 1
    Why are you returning raw forms of your interface and class? Also, Java has return type covariance; you can override baz to return a Class, or a Class<T, U> once the rawness has been eliminated. (I know it's just an example, but it's a poor choice of class name due to the existing java.lang.Class class.) Commented Aug 12, 2019 at 23:12
  • 1
    Possible duplicate of Is there a way to refer to the current type with a type variable? Commented Aug 12, 2019 at 23:13
  • Possible duplicates: Builder Pattern and Inheritance and Subclassing a Java Builder class. Commented Aug 12, 2019 at 23:15
  • My apologies @shmosel. I thought that the reason my code was failing with return type Class was because of overloading problems. The actual reason is because in my actual implementation, the baz() function is implemented in an abstract class between Interface and Class, so even if it were to return AbstractClass, this would not be enough of a downcast for Class to use. Thank you for the suggestion @rgettman, the reason I have not used return type covariance is because it is not an easily extensible solution for multiple inheriting layers of concrete classes Commented Aug 12, 2019 at 23:34

1 Answer 1

1

If you want the interface to return an defined type, then you need another type parameter (e.g. named W), and you'd want to make sure that type is an Interface, so:

public interface MyInterface<T, U, W extends MyInterface<T, U, W>> {
    public void foo(T t, U u);

    public W baz();
}

public class MyClass<T, U> implements MyInterface<T, U, MyClass<T, U>> {
    @Override
    public void foo(T t, U u) {}

    public MyClass<T, U> bar() {
        return this;
    }

    @Override
    public MyClass<T, U> baz() {
        return this;
    }
}

Note: Added prefix My to avoid confusion with built-in class named Class.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.