Kotlin泛型类型问题

时间:2017-12-06 21:16:10

标签: generics kotlin

我在通用类型中迷失了很多个小时。我想简化代码,但我不能在其泛型类型时强制转换对象。我怎么能解决这个问题或其他简化方法? (I'm use kotlin 1.2)

sealed class SETTING(override val key: String) : SettingsKeyContract

object optFirstLaunch : SETTING("first_launch"), SettingsKeyContractWithType<Boolean> {
    override val defaults = true
}

object optNotifications : SETTING("notification_list"), SettingsKeyContractWithType<List<String>> {
    override val defaults = emptyList<String>()
}

interface SettingsKeyContract { val key: String }
interface SettingsKeyContractWithType<T : Any> : SettingsKeyContract {

    val defaults: T

    @Suppress("UNCHECKED_CAST")
    fun get(): T?       = (App.getContentComponent()?.getSettings()?.get(key)?.value?.data as? T)
    fun remove()        = (App.getContentComponent()?.getSettings())?.delete(key)
    fun save(value: T)  = (App.getContentComponent()?.getSettings()?.add(key, value))

}

class OptionModel(@OPTIONS_ID optionId: Int, contract: SettingsKeyContract)

val optionModel = OptionModel(1, optNotifications)
when(optionModel.contract){
    is SettingsKeyContractWithType<List<String>> -> (optionModel.contract as SettingsKeyContractWithType<List<String>>).set(listOf("ring-1", "ring-2")) //error
    is SettingsKeyContractWithType<Boolean> -> (optionModel.contract as SettingsKeyContractWithType<Boolean>).set(true)  //error
}

错误:

Cannot check for instance of erased type: SettingsKeyContractWithType<...>

1 个答案:

答案 0 :(得分:2)

请在语言参考中查看类型擦除的说明和类型检查通用类型:Type erasure and generic type checks

基本上,你不能进行那种检查,因为SettingsKeyContractWithType的实例在运行时没有任何关于它们的实际类型参数的信息。

您可以在此处尝试的一个选项是添加make SettingsKeyContractWithType显式存储类型参数的一些表示形式。一个简单的KClass似乎不合适,因为它不能代表具体的泛型类型(KClass不能有List<String>

如果这真的是你想要的,请考虑使用超类型令牌技术,如下所述:(link)

您可以将TypeReference<T>属性添加到SettingsKeyContractWithType,并在内联工厂函数中使用带有参数的类型参数填充它。