Here is a piece of code I'm working on. I have a Callback object that can return a specified super type. Vehicle is one of these classes here. These classes are used as supertype for other classes like Car and Train here.
interface CompletionCallBack<Result> {
void onCompletion(Result result);
}
class Vehicle {
Map<String, Object> attributes;
}
class Car extends Vehicle {
public String getMake(){
return attributes.get("make").toString();
}
}
class Train extends Vehicle {
public String getMake(){
return attributes.get("size").toString();
}
}
public class Main {
static void execute(CompletionCallBack<Vehicle> callBack) {
callBack.onCompletion(new Vehicle());
}
public static void main(String[] args) {
execute(new CompletionCallBack<Vehicle>() {
@Override
public void onCompletion(Vehicle result) {
Car car = (Car) result; //Exception
}
});
execute(new CompletionCallBack<Vehicle>() {
@Override
public void onCompletion(Vehicle result) {
Train train = (Train) result; //Exception
}
});
}
}
Here I get ClassCastException as Vehicule cannot be directly casted to Car or Train. I would like to either call the execute giving it a type like Car or Train like so :
public class Main {
static void executeGeneric(CompletionCallBack<? extends Vehicle> callBack) {
callBack.onCompletion(new Vehicle()); //compilation error
}
public static void main(String[] args) {
executeGeneric(new CompletionCallBack<Car>() {
@Override
public void onCompletion(Car car) {
//I receive a car here
}
});
}
}
I'm trying to do this because in my case, Vehicle contains a map of attribute and a Car a vehicle that has some key-value pair in that list. Train has others. My Car and Train object provides easy getter that knows the specific keys to retrieve data from the Map.
The only way I was able to do it was to remove the parent-child relation and build a decorator around a Vehicle for my Train and Car classes.
instanceofkeyword to determine if the runtime object is of a given subtype. Additionally, you cannot cast a superclass into a subclass type unless the object itself was initialized as the subclass type.executefunction will always work with the superclass. Maybe my question would be : How to go from a superclass to a subclass without manually copying fields?new Vehicleand get aCar. The runtime is right to throw an invalid cast - a vehicle is not car; it's the other way around.finalfields present in a given subclass populated in the constructor. If we could cast a superclass type directly to a subclass type, what would be the value of these fields (since the superclass type never invoked the subclass constructor)?