Вы не можете выразить это отношение типа способом, понятным компилятору Java.Но вы можете получить аналогичный эффект, если узнаете BusRequest
типы о типе Bus
, с которым они должны использоваться, и узнаете Bus
, какой это тип шины.
Например:
// B is the type of the Bus subclass
public interface Bus<B extends Bus<B>> {
// R is the response type, and Q is the request type
<R, Q extends BusRequest<R, B>> R execute(Q request);
}
// a request is parameterized by R, the response type, and B, the bus type
public interface BusRequest<R, B extends Bus<B>> {}
// A CommandBus is a Bus for CommandBusRequests
public static class CommandBus implements Bus<CommandBus> {
@Override
public <R, Q extends BusRequest<R, CommandBus>> R execute(Q request) {
System.out.println("Got request of type: " + request.getClass());
return null;
}
}
public interface CommandBusRequest<T> extends BusRequest<T, CommandBus> {}
// StringCommandBusRequest is a BusRequest for a CommandBus that requests
// a response of type String
public static class StringCommandBusRequest
implements CommandBusRequest<String> {}
Все эти типы компилируются и проверяются на тип, и результат выглядит так, как я думаю:
public static void main(String[] args) throws Exception {
StringCommandBusRequest request = new StringCommandBusRequest();
Bus<CommandBus> bus = new CommandBus();
String result = bus.execute(request);
}
Демонстрация: https://ideone.com/U1TLXr
Однако, чтобы быть более полезным, вам, вероятно, понадобится некоторая информация о полезной нагрузке шины для каждого объекта запроса.При этом каждый тип запроса привязан к типу шины, но шина не может извлечь данные, относящиеся к шине, из объекта запроса, потому что, например, может быть несколько классов, которые реализуют BusRequest<?, CommandBus>
.
Чтобы решить эту проблему, нам просто нужно ввести другой (!) Параметр типа, чтобы отслеживать тип полезной нагрузки.Например:
public interface Bus<P, B extends Bus<P, B>> {
<R, Q extends BusRequest<R, P, B>> R execute(Q request);
}
public interface BusRequest<R, P, B extends Bus<P, B>> {
P getPayload();
}
public static class CommandBus
implements Bus<CommandBusRequestPayload, CommandBus> {
@Override
public <R, Q extends BusRequest<R, CommandBusRequestPayload, CommandBus>>
R execute(Q request) {
CommandBusRequestPayload payload = request.getPayload();
System.out.println("Got payload: " + payload);
return null;
}
}
public static abstract class CommandBusRequest<T>
implements BusRequest<T, CommandBusRequestPayload, CommandBus> {
@Override
public CommandBusRequestPayload getPayload() {
return new CommandBusRequestPayload();
}
}
public static class CommandBusRequestPayload {}
public static class StringCommandBusRequest
extends CommandBusRequest<String> {}
Демо с полезной нагрузкой: https://ideone.com/2aUwMW