My Question might be very simple,
I have a class Result
with some inner fields , setters and getters.
Additionally, i have class Special1Result
which extends Result
and includes several more fields and Special2Result
with some more data.
In different class Dispatcher
, i have written the following method:
processResults(List<? extends Result> results)
, which is only familiar with Result
(I need this method to query if there is specific field in the extended Result object - i am using annotations).
So i have decided to use the extended for-each loop: for (Result res : results) {}
So what is my question ? i am trying to find over the web how to write this for loop for extended objects, e.g. something like this for (? extends Results res: results){}
Is it possible? How is the correct way to write it?
All you know about a List<? extends Result>
is that each element will be a Result
- so that's all you can put in the enhanced for loop syntax.
If you need members which aren't declared in Result
, you'll need to cast inside the loop:
for (Result result : results) {
if (result instanceof CleverResult) {
CleverResult clever = (CleverResult) result;
// Use clever here
}
}
Think about what you'd write if you weren't using an enhanced for loop - you'd still need to write the cast, wouldn't you?
Of course, if you know that the list should really only contain one specific type, you can always cast unconditionally in the loop.
I am trying to find over the web how to write this for loop for extended objects, e.g. something like this
for (? extends Results res: results){}
No, this is not possible: you cannot statically type items supplied dynamically at run-time.
How is the correct way to write it?
You are already doing it:
for (Results res: results) {
}
If you would like to test for Special2Result
inside that loop, you can do it, but usually it tells that your design can be improved. A better alternative is to use a mechanism of double dispatch, such as the Visitor Pattern, to hide the details of special treatment for your subclasses.
Java has type erasure - the concrete type parameters of collections are not present at runtime.
So if you have a List, the java compiler will ensure that no code will put anything into the list that isnt a subclass of Result.
Accordingly, at runtime, all your loop can know is that the contents are all subclasses of Result - so the only way to loop over them is as a set of references to Result, with whatever polymorphic behaviour that is present as a result of any subclasses that are in the list.
Since your concrete sublasses only differs by nature of fields, I would suggest you to benefit from simple polymorphism.
You would end up with a Result
interface/abstract class defining an execute()
method class implemented by as many classes or subclasses as you need containing themselves action to do.
Therefore, your client code could merely use:
for (Result res : results){ //results being as a List<Result> type
res.execute();
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With