Reputation: 87
I currently have a class test which transforms a stream to a stream of same type.
class Test {
private Function<A1, A1> a1Transform;
private Function<A2, A2> a2Transform;
public <T extends A> Stream<T> transform(Stream<T> input) {
return input
.filter(o -> o instanceof A1)
.map(A1.class::cast)
.map(a1Transform);
}
}
The code doesn't compile unless
Stream<? super T>
or .map(o -> (T) o)
to cast it back to T. Is either of the solutions any good. What would be a better way to approach this problem.
Upvotes: 1
Views: 1264
Reputation: 37845
If A1
, A2
, etc. have a common supertype A
, then you could change the method to something like the following:
public Stream<A> transform(Stream<?> input) {
return input.filter(o -> o instanceof A1)
.map(o -> (A1) o)
.map(a1Transform)
.map(o -> (A) o);
}
There's no way for a method to return, say, either Stream<A1>
, or Stream<A2>
, or Stream<A3>
, etc. The best you can do is like the above, where you return a Stream<A>
, or you could return a Stream<? extends A>
.
If it's really important to return a stream with the exact type of the elements, then you could use something like the visitor pattern, and pass the visitor in to the method instead of returning the stream directly.
Another possible way could be for the caller to pass a Class
in to the method:
public <T extends A> Stream<T> transform(Stream<?> input, Class<T> type) {
return input...
...
...
.map(type::cast);
}
However, running in to this kind of problem is usually an indication that you need to redesign something. In general, in object-oriented design, code which is external to your API should not be concerned with having specific types of objects.
Upvotes: 1