I don't really see your problem. Note that the generic type information is erased at runtime (at least for the JVM-variant which you are obviously using). So it basically doesn't matter which generically typed service you use.
You can also just use VehicleStarterService<Vehicle>
and it will start all your vehicles. If for any reason you need to call a specific (other!) function you still need to check/cast to your actual type... So I see no benefit in trying to get that generic typed interface.
Having said that there are still methods to do it... (note again: it doesn't really matter... generic type information is erased at runtime...)
Now for my tests I use this entry method:
fun startAllTheVehicles(vararg vehicleTypes: String) {
startAllTheVehicles(*vehicleTypes.map { Class.forName(it) }
.map { it as Class<out Vehicle> }
.toTypedArray())
}
Note that it as Class<out Vehicle>
is NOT ensuring that you have a class of type Vehicle
. It just makes sure that your code compiles when trying to call your functions that declare Class<out Vehicle>
as a parameter type.
So starting from there you could use one of the following ways to have an actual generic type available. I am assuming you use something like newInstance
within your start service.
Sample with the generic type omitted on the interface (that case is rather easy):
interface VehicleStarterService {
fun <T: Vehicle> start(vehicleType: Class<T>) = vehicleType.newInstance().start
}
Sample method that is called by the above entry function using one service to start all vehicles:
fun <T : Vehicle> startAllTheVehicles(vararg vehicleTypes: Class<out T>) {
val service = object : VehicleStarterService {}
vehicleTypes.forEach { service.start(it) }
}
Still using an interface with generic type (note the changes regarding out T
, etc.):
interface VehicleStarterService<T: Vehicle> {
fun start(vehicleType: Class<out T>) = vehicleType.newInstance().start
}
Sample method that is called by the entry function using one service to start all vehicles:
fun <T : Vehicle> startAllTheVehicles(vararg vehicleTypes: Class<out T>) {
// actually it doesn't really matter which type we use...
val service = object : VehicleStarterService<Vehicle> {} // you could even use T instead of Vehicle
vehicleTypes.forEach { service.start(it) }
}
Testing both with the following works as expected:
startAllTheVehicles("Car", "Truck")
Calling it with a type that is actually no Vehicle
will give you a ClassCastException
at the interface's start
-function.