widavies
widavies

Reputation: 976

Generic that Extends a Generic, Passing Down Type

Forgive me if this question is a duplicate, I just have no idea how to phrase a Google search to come up with an answer.

First, I have an abstract class called AsyncRoutine<Msg>, it's generic, and specifies some sort of Msg type.

Next, I have an abstract AsyncMessageProvider<T extends AsyncRoutine>, designed to deliver a Msg to an AsyncRoutine.

Let's say I create a subclass MyAsyncRoutine<Integer> that extends AsyncRoutine. I'd like to make a AsyncMessageProvider that supports this class, so I'll subclass it, MyAsyncMessageProvider<MyAsyncRoutine> making MyAsyncRoutine its generic type.

Within MyAsyncMessageProvider, I have a method, message(...) that is called to pass a Msg along, in this case an Integer.

public class MyAsyncMessageProvider extends AsyncMessageProvider<MyAsyncRoutine> {

    protected void message(Msg msg) { // compile error, doesn't know what 'Msg' is
    }

}

How can I access the generic type of MyAsyncRoutine (Integer) within AsyncMessageProvider? I basically want to make the message(...) function lock to whatever I specify in <> as I'm subclassing AsyncMessageProvider

Is it possible to do this without reflection? Or is there a better way to do this in general? I'd like to avoid using reflection if possible.

Minimum Viable Example

Abstract class definitions:

public abstract class AsyncRoutine<Msg> {
 // Implementation not important
}
public abstract class AsyncMessageProvider<Routine extends AsyncRoutine<Msg>> { // Compile error, cannot resolve Msg
    abstract void messageRoutine(Msg m); 
}

Upvotes: 1

Views: 79

Answers (1)

Bohemian
Bohemian

Reputation: 424983

Add a type for it to your subclass:

public abstract class AsyncMessageProvider<Msg, Routine extends AsyncRoutine<Msg>> {
    abstract void messageRoutine(Msg m); 
}

——

Although this will compile, it’s the convention to use single letters for type names, ie:

public abstract class AsyncMessageProvider<T, Routine extends AsyncRoutine<T>> {
    abstract void messageRoutine(T t); 
}

Doing this makes it clear to readers what the type is, because they’re used to seeing single letter names. Someone reading this:

abstract void messageRoutine(Msg m);

would be excused if they thought the method was expecting an instance of a class named Msg.

The problem become worse when you actually have a class named Msg because the type of the same name shadows the corresponding class, which will make your coworkers sad.

Upvotes: 1

Related Questions