I have an interface that I need to implement. It looks something like this:
public interface SimulationState {
...
public Iterable<VehicleStatus> getVehicleStatuses();
}
I am trying to extend the interface into some sort of a decorator interface as the following:
public interface SimulationStateDec<V extends VehicleStatus> extends SimulationState {
...
@Override
public Iterable<V> getVehicleStatuses();
}
OR
public interface SimulationStateDec<V extends VehicleStatus> extends SimulationState {
...
@Override
public Iterable<? extends VehicleStatus> getVehicleStatuses();
}
Here's the concrete class I'm implementing the interface at:
public class WareHouseState implements SimulationState {
...
@Override
public Iterable<VehicleStatus> getVehicleStatuses() {
return this.vStatuses;
}
}
I am implementing the VehicleStatus interface at a class named VehicleState so i could return the implemented VehicleState though the Iterable in my concrete class
So at a class in my project I am calling the getVehicleStatuses() method
and I am obligated to cast every element to VehicleState as the following:
public class Gate {
...
private ArrayList<VehicleThread> vehicles;
public Gate(WareHouse wareHouse, GatePriority priority) {
...
this.vehicles = new ArrayList<>();
wareHouseState.getVehicleStatuses().forEach(v -> vehicles.add(new VehicleThread((VehicleState) v, wareHouse)));
sortSameTimeArrivalBy(priority);
}
}
I know I am doing something wrong here, I was wondering if that way of implementation is allowed. Compiler tells me to change the method in the implemented interface and it's not applicable for my application has to work on a different framework.
I need to return a variety of concrete types that implements the same interface without having to cast every element.
You can't, because when overriding you can only narrow down the return type, and neither Iterable<V> nor Iterable<? extends VehicleStatus> are subtypes of Iterable<VehicleStatus>.
In Java 8 you could perhaps add the new method without overriding and implement the old one as a default (or use abstract class in previous versions):
public interface SimulationStateDec<V extends VehicleStatus> extends SimulationState {
...
Iterable<V> getVehicleStatusesDec();
default Iterable<VehicleStatus> getVehicleStatuses() {
return (Iterable<VehicleStatus>) getVehicleStatusesDec();
}
}
This should be safe because Iterable<T> doesn't have any methods which take T as argument: it "should" be covariant except Java doesn't support that; doing the same with e.g. List is a bad idea!
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