以下示例:
我有一项可以"启动"任何车辆的服务
interface VehicleStarterService<T: Vehicle> {
fun <T : Vehicle> start(vehicle: Class<T>): String {
return vehicle.start
}
}
我想通过名称启动一个车辆类型,如"Car",这将需要我创建一个 VehicleStarterService;但是我似乎找不到一种方法来实例化一个由名称实例化的类的接口。
我想做类似的事情(但不能(:
val cls = "Car"
val kClass = Class.forName(cls).kotlin
val service = VehicleStarterService<kClass>()
service.start
我最终不得不执行以下操作(为我需要的每个参数化类型创建一个服务(:
class CarStarterService : VehicleStarterService<Car> {
fun <T> execute() : String {
return start(User::class.java)
}
}
有没有办法以这种方式实例化参数化的类?
目前尚不清楚这是否足以满足您的情况,但也许您可以像这样根据字符串匹配类
val cls = "Car"
val service: VehicleStarterService<out Vehicle>? = when (cls) {
"Car" -> object : VehicleStarterService<Car> {}
"Boat" -> object : VehicleStarterService<Boat> {}
"Plane" -> object : VehicleStarterService<Plane> {}
else -> null
}
service?.start(...
编辑:哈希图注册表的想法允许一些可扩展性。
val serviceRegistry = HashMap<String, VehicleStarterService<out Vehicle>>()
.apply {
//default services
this["Car"] = object : VehicleStarterService<Car> {}
this["Boat"] = object: VehicleStarterService<Boat> {}
}
.
.
.
//Adding entry
serviceRegistry["Plane"] = object: VehicleStarterService<Plane> {}
.
.
.
//Fetching entry
val cls = "Car"
val service = serviceRegistry[cls]
service?.start(...
我真的看不出你的问题。请注意,泛型类型信息在运行时被擦除(至少对于您显然正在使用的 JVM 变体(。因此,使用哪种通用类型服务基本上无关紧要。 您也可以只使用VehicleStarterService<Vehicle>
,它将启动您的所有车辆。如果出于任何原因你需要调用一个特定的(其他!(函数,你仍然需要检查/强制转换为你的实际类型......因此,我认为尝试获取该通用类型化接口没有任何好处。
话虽如此,仍然有方法可以做到这一点...(再次注意:这并不重要...泛型类型信息在运行时被擦除...
现在对于我的测试,我使用这个输入方法:
fun startAllTheVehicles(vararg vehicleTypes: String) {
startAllTheVehicles(*vehicleTypes.map { Class.forName(it) }
.map { it as Class<out Vehicle> }
.toTypedArray())
}
请注意,it as Class<out Vehicle>
并不能确保您具有类型Vehicle
的类。它只是确保代码在尝试调用将Class<out Vehicle>
声明为参数类型的函数时进行编译。
因此,从那里开始,您可以使用以下方法之一来提供实际的泛型类型。我假设您在启动服务中使用类似newInstance
的东西。
接口上省略泛型类型的示例(这种情况相当容易(:
interface VehicleStarterService { fun <T: Vehicle> start(vehicleType: Class<T>) = vehicleType.newInstance().start }
上述入口函数调用的示例方法,使用一个服务启动所有车辆:
fun <T : Vehicle> startAllTheVehicles(vararg vehicleTypes: Class<out T>) { val service = object : VehicleStarterService {} vehicleTypes.forEach { service.start(it) } }
仍然使用泛型类型的接口(请注意有关
out T
等的更改(:interface VehicleStarterService<T: Vehicle> { fun start(vehicleType: Class<out T>) = vehicleType.newInstance().start }
入口函数使用一个服务启动所有车辆的示例方法:
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) } }
按预期使用以下方法测试两者:
startAllTheVehicles("Car", "Truck")
使用实际上没有Vehicle
的类型调用它会使您在接口的start
函数中ClassCastException
。