I made this simplified example of my real code, it is not compiling:
public class Example {
public static void main(String[] args) {
Callback<BalanceResponse> balanceRequestCaller = new Callback<BalanceResponse>() {
@Override
public void onResponse(BalanceResponse response) {}
@Override
public void onFailure(String error, int code) {}
@Override
public void onFailure(Throwable t) {}
};
BalanceRequest breq = new BalanceRequest();
Interceptor interceptor = new Interceptor(balanceRequestCaller);
breq.startRequest((Callback<BaseResponse>) interceptor); //compile-time error!!!
}
public static class Interceptor implements Callback<BaseResponse> {
public Interceptor(Callback<? extends BaseResponse> originalCaller) {
this.originalCaller = originalCaller;
}
private Callback<? extends BaseResponse> originalCaller;
@Override
public void onResponse(BaseResponse response) {
//do some interception stuff
if (response instanceof BalanceResponse) {
((Callback<BalanceResponse>) originalCaller).onResponse((BalanceResponse) response);
} else if (response instanceof SubscriptionResponse) {
((Callback<SubscriptionResponse>) originalCaller).onResponse((SubscriptionResponse) response);
}
}
@Override
public void onFailure(String error, int code) {}
@Override
public void onFailure(Throwable t) {}
}
public interface Request<T extends BaseResponse> {
void startRequest(Callback<T> callback);
}
public static class BalanceRequest implements Request<BalanceResponse> {
@Override
public void startRequest(Callback<BalanceResponse> callback) {}
}
public static class SubscriptionRequest implements Request<SubscriptionResponse> {
@Override
public void startRequest(Callback<SubscriptionResponse> callback) {}
}
public static class BaseResponse {
public String status;
}
public static class BalanceResponse extends BaseResponse {
}
public static class SubscriptionResponse extends BaseResponse {
}
public interface Callback<T> {
void onResponse(T response);
void onFailure(String error, int code);
void onFailure(Throwable t);
}
}
What I am trying to do is make an Interceptor
that would intercept the callback, do some stuff with the response and then pass it on to the original callback.
I want to make a generic Interceptor
that could intercept any callback that is Callback<? extends BaseResponse>
Callback<? extends BaseResponse>
.
By the way the compile-time error I am getting from NetBeans is
incompatible types: Callback<BaseResponse> cannot be converted to Callback<BalanceResponse>
Give me suggestions how could I make this work?
You should define a type parameter on your class Interceptor
to prevent your compilation error and to avoid explicit casts in the method onResponse
which is generally a proof of design issue.
Your Interceptor class with a type parameter :
public static class Interceptor<T extends BaseResponse> implements Callback<T> {
public Interceptor(Callback<T> originalCaller) {
this.originalCaller = originalCaller;
}
private Callback<T> originalCaller;
@Override
public void onResponse(T response) {
originalCaller.onResponse(response);
}
...
}
You would then instantiate it and use it as next:
Interceptor<BalanceResponse> interceptor = new Interceptor<>(balanceRequestCaller);
breq.startRequest(interceptor);
Change the signature of startRequest()
signature to
void startRequest(Callback<? super T> callback);
This allows it to accept a more generic callback, instead of requiring only the narrowest type. For more info, see What is PECS (Producer Extends Consumer Super)?
EDIT: @teppic's answer is the better solution, unless you must reuse a single Interceptor
instance for different request types. If that is the case, you can still reduce the boilerplate to a single delegation:
@Override
public void onResponse(BaseResponse response) {
//do some interception stuff
((Callback<BaseResponse>)originalCaller).onResponse(response);
}
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.