Kotlin generic factory динамическое приведение

Я хочу создать фабрику объектов с общим параметром:

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)
)

Любые идеи, как бросить его правильно? Или какие-то идеи "другого подхода"?

Как создавать пользовательские общие типы в Python (50/100 дней Python)
Как создавать пользовательские общие типы в Python (50/100 дней Python)
Помимо встроенных типов, модуль типизации в Python предоставляет возможность определения общих типов, что позволяет вам определять типы, которые могут...
1
0
636
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

Боюсь, вам просто нужно сделать непроверенный кастинг.

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()

Другие вопросы по теме