Kotlin 通用工厂动态转换
Kotlin generic factory dynamic cast
我想创建具有通用参数的对象工厂:
interface Foo<T> {
fun buzz(param: T)
}
我有两个测试实现:
class FooImpl1 : Foo<String> {
override fun buzz(param: String) {
// implementation 1
}
}
class FooImpl2 : Foo<Int> {
override fun buzz(param: Int) {
// implementation 2
}
}
现在我已经创建了包含我所有实现的地图
val implementationMap = mapOf<String, Foo<*>>(
Pair(firstKey, FooImpl1()),
Pair(secKey, FooImpl2())
)
我还有带参数的地图:
val paramMap = mapOf<String, Any>(
Pair(firstKey, "String param"),
Pair(secKey, 12)
)
但现在当我从地图中获取第一个元素时:
implementationMap.getValue(firstKey).buzz(paramMap.getValue(firstKey))
我的 buzz
方法拒绝任何参数(需要 Nothing
作为类型)
所以我创建了另一个类型为
的地图
val classMap = mapOf<String, KClass<*>>(
Pair(firstKey, FooImpl1::class),
Pair(secKey, FooImpl2::class)
)
val paramClassMap = mapOf<String, KClass<*>>(
Pair(firstKey, String::class),
Pair(secKey, Int::class)
)
但我不能那样投:
implementationMap.getValue(firstKey)
.cast < classMap.getValue(firstKey) > () // not possible
.buzz(
paramMap.getValue(firstKey)
.cast < paramClassMap.getValue(firstKey) > () // not possible
)
或者那个
(implementationMap.getValue(firstKey) // FooImpl1
/*not possible */ as classMap.getValue(firstKey)) // (FooImpl1::class)
.buzz(
paramMap.getValue(firstKey) // String
/*not possible */ as paramClassMap.getValue(firstKey)) // (String::class)
我也尝试过使用 Token
类型,但它对天气没有帮助:
val classMap = mapOf<String, Type>(
Pair(firstKey, object: TypeToken<FooImpl1>() {}.type),
Pair(secKey, object: TypeToken<FooImpl1>() {}.type)
)
知道如何正确投射吗?或者一些 "different approach" 想法?
恐怕你只需要做一些未经检查的转换。
interface Foo<T> {
fun buzz(param: T)
}
class FooImpl1 : Foo<String> {
override fun buzz(param: String) {
println(param)
}
}
class FooImpl2 : Foo<Int> {
override fun buzz(param: Int) {
println(param)
}
}
val implementationMap = mapOf<String, Foo<*>>(
Pair("firstKey", FooImpl1()),
Pair("secKey", FooImpl2())
)
val paramMap = mapOf<String, Any>(
Pair("firstKey", "String param"),
Pair("secKey", 12)
)
fun main() {
@Suppress("UNCHECKED_CAST")
val imp = implementationMap["firstKey"] as Foo<Any?>
val param = paramMap["firstKey"]
imp.buzz(param)
}
好吧,如果你能把它们组合在一起...
class FooWithParam<T>(foo: Foo<T>, param: T) {
fun doBuzz() = foo.buzz(param)
}
val fooWithParamMap = mapOf<String, FooWithParam<*>>(
Pair(firstKey, FooWithParam(FooImpl1(), "String param"),
Pair(secKey, FooWithParam(FooImpl2(), 12))
)
implementationMap[firstKey].doBuzz()
我想创建具有通用参数的对象工厂:
interface Foo<T> {
fun buzz(param: T)
}
我有两个测试实现:
class FooImpl1 : Foo<String> {
override fun buzz(param: String) {
// implementation 1
}
}
class FooImpl2 : Foo<Int> {
override fun buzz(param: Int) {
// implementation 2
}
}
现在我已经创建了包含我所有实现的地图
val implementationMap = mapOf<String, Foo<*>>(
Pair(firstKey, FooImpl1()),
Pair(secKey, FooImpl2())
)
我还有带参数的地图:
val paramMap = mapOf<String, Any>(
Pair(firstKey, "String param"),
Pair(secKey, 12)
)
但现在当我从地图中获取第一个元素时:
implementationMap.getValue(firstKey).buzz(paramMap.getValue(firstKey))
我的 buzz
方法拒绝任何参数(需要 Nothing
作为类型)
所以我创建了另一个类型为
的地图val classMap = mapOf<String, KClass<*>>(
Pair(firstKey, FooImpl1::class),
Pair(secKey, FooImpl2::class)
)
val paramClassMap = mapOf<String, KClass<*>>(
Pair(firstKey, String::class),
Pair(secKey, Int::class)
)
但我不能那样投:
implementationMap.getValue(firstKey)
.cast < classMap.getValue(firstKey) > () // not possible
.buzz(
paramMap.getValue(firstKey)
.cast < paramClassMap.getValue(firstKey) > () // not possible
)
或者那个
(implementationMap.getValue(firstKey) // FooImpl1
/*not possible */ as classMap.getValue(firstKey)) // (FooImpl1::class)
.buzz(
paramMap.getValue(firstKey) // String
/*not possible */ as paramClassMap.getValue(firstKey)) // (String::class)
我也尝试过使用 Token
类型,但它对天气没有帮助:
val classMap = mapOf<String, Type>(
Pair(firstKey, object: TypeToken<FooImpl1>() {}.type),
Pair(secKey, object: TypeToken<FooImpl1>() {}.type)
)
知道如何正确投射吗?或者一些 "different approach" 想法?
恐怕你只需要做一些未经检查的转换。
interface Foo<T> {
fun buzz(param: T)
}
class FooImpl1 : Foo<String> {
override fun buzz(param: String) {
println(param)
}
}
class FooImpl2 : Foo<Int> {
override fun buzz(param: Int) {
println(param)
}
}
val implementationMap = mapOf<String, Foo<*>>(
Pair("firstKey", FooImpl1()),
Pair("secKey", FooImpl2())
)
val paramMap = mapOf<String, Any>(
Pair("firstKey", "String param"),
Pair("secKey", 12)
)
fun main() {
@Suppress("UNCHECKED_CAST")
val imp = implementationMap["firstKey"] as Foo<Any?>
val param = paramMap["firstKey"]
imp.buzz(param)
}
好吧,如果你能把它们组合在一起...
class FooWithParam<T>(foo: Foo<T>, param: T) {
fun doBuzz() = foo.buzz(param)
}
val fooWithParamMap = mapOf<String, FooWithParam<*>>(
Pair(firstKey, FooWithParam(FooImpl1(), "String param"),
Pair(secKey, FooWithParam(FooImpl2(), 12))
)
implementationMap[firstKey].doBuzz()