suit
suit

Reputation: 581

Generic type parameter as method argument

I have generic interface:

public interface StreamObserver<V>  {
    void onNext(V value);
}

And have to create objects for different types (SubscribeTradesResponse and SubscribeOrderResponse):

1)

StreamObserver<SubscribeTradesResponse> getTradesResponseStream() {
    return new StreamObserver<SubscribeTradesResponse>() {
        @Override
        public void onNext(SubscribeTradesResponse response) {
            responseOnNextAction(response);
        }
    };
}

2)

StreamObserver<SubscribeOrderResponse> getOrderResponseStream() {
    return new StreamObserver<SubscribeOrderResponse>() {
        @Override
        public void onNext(SubscribeOrderResponse response) {
            responseOnNextAction(response);
        }
    };
}

Is it possible to make a common method getResponseStream() and pass SubscribeTradesResponse or SubscribeOrderResponse as an argument?

Upvotes: 0

Views: 119

Answers (2)

daniu
daniu

Reputation: 14999

You can create a common interface for the two response types:

interface TradeOrOrderResponse {
}

with

class SubscribeTradesResponse implements TradeOrOrderResponse

and

class SubscribeOrderResponse implements TradeOrOrderResponse

and then extend your observer-interface

public interface TOResponseObserver extends StreamObserver<V extends TradeOrOrderResponse>  {
    void onNext(V value);
}

and if your responseOnNextAction takes that interface

void responseOnNextAction(TradeOrOrderResponse resp)

it implements the TOResponseObserver interface, ie you can use it to handle either SubscribeTradesResponse or SubscribeOrderResponse objects.

Upvotes: 2

ernest_k
ernest_k

Reputation: 45309

You can do even better by using lambda expressions, which will allow you to get rid of getTradesResponseStream and getOrderResponseStream:

StreamObserver<SubscribeTradesResponse>  tradeObserver= response -> 
      responseOnNextAction(response);
//or
StreamObserver<SubscribeTradesResponse>  tradeObserver= 
      this::responseOnNextAction;

StreamObserver<SubscribeOrderResponse> orderObserver = response -> 
      responseOnNextAction(response);
//or
StreamObserver<SubscribeOrderResponse> orderObserver = 
      this::responseOnNextAction;

That assumes you have overloaded responseOnNextAction accordingly.

But if you were to use the inner classes, you can still make the method generic:

<T> StreamObserver<T> getTradesResponseStream() {
    return new StreamObserver<T>() {
        @Override
        public void onNext(T response) {
            responseOnNextAction(response);
        }
    };
}

But this depends on the signature of responseOnNextAction. It will work as is if the method takes an Object, but if it takes a Response of a sort, you may have to change the type parameter to
<T extends Response>

Upvotes: 2

Related Questions