我在通用类型中迷失了很多个小时。我想简化代码,但我不能在其泛型类型时强制转换对象。我怎么能解决这个问题或其他简化方法? (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<...>
答案 0 :(得分:2)
请在语言参考中查看类型擦除的说明和类型检查通用类型:Type erasure and generic type checks。
基本上,你不能进行那种检查,因为SettingsKeyContractWithType
的实例在运行时没有任何关于它们的实际类型参数的信息。
您可以在此处尝试的一个选项是添加make SettingsKeyContractWithType
显式存储类型参数的一些表示形式。一个简单的KClass
似乎不合适,因为它不能代表具体的泛型类型(KClass
不能有List<String>
。
如果这真的是你想要的,请考虑使用超类型令牌技术,如下所述:(link)。
您可以将TypeReference<T>
属性添加到SettingsKeyContractWithType
,并在内联工厂函数中使用带有参数的类型参数填充它。