generics - 如何使用泛型获取枚举的值?

标签 generics kotlin

我想提供这个问题的背景。我见过独特的解决方案,人们创建将从 SharedPreferences 而不是支持字段读取/写入的委托(delegate)。例如,要对字符串执行此操作:

class SharedPrefsString(private val sharedPrefs: SharedPreferences) {
    operator fun getValue(thisRef: Any?, property: KProperty<*>): String {
        return sharedPrefs.getString(property.name, "")
    }

    operator fun setValue(thisRef: Any?, property: KProperty<*>, value: String) {
        sharedPrefs.edit().putString(property.name, value).apply()
    }
}

var myString: String by SharedPrefsString(myPrefs)

但是,我希望可以对通用枚举执行相同的操作,因为所有枚举都有 valueOf(string) 方法,但下面的方法不起作用。我在评论中放了一些我尝试过的东西:

class SharedPrefsEnum<T : Enum<T>>(private val sharedPrefs: SharedPreferences) {
    operator fun getValue(thisRef: Any?, property: KProperty<*>): T {
        // Doesn't work, can't reference T, which makes sense. 
        // return T.valueOf(sharedPrefs.getString(property.name, ""))

        // Can't use reified type here, which makes sense.
        // return enumValueOf<T>(sharedPrefs.getString(property.name, ""))
    }

    operator fun setValue(thisRef: Any?, property: KProperty<*>, value: T) {
        sharedPrefs.edit().putString(property.name, value.name).apply()
    }
}

var myEnum: MyEnum by SharedPrefsEnum(myPrefs)

这样的事情可能吗?

最佳答案

根据您的答案,您可以使用 enumConstants 属性避免使用反射:

class SharedPrefsEnum<T : Enum<T>>(
    private val sharedPrefs: SharedPreferences, 
    private val clazz: Class<T>
) : ReadWriteProperty<Any, T> {
    operator fun getValue(thisRef: Any, property: KProperty<*>): T {
        val enumName = sharedPrefs.getString(property.name, "")
        return clazz.enumConstants.find { it.name == enumName }!!
    }

    operator fun setValue(thisRef: Any, property: KProperty<*>, value: T) {
        sharedPrefs.edit().putString(property.name, value.name).apply()
    }
}

然后您可以使用以下方式轻松添加委托(delegate):

inline fun <reified T : Enum<T>> sharedPreferences(prefs: SharedPreferences) = 
    SharedPrefsEnum(prefs, T::class.java)

允许您分配它:

private var myEnum: MyEnum by sharedPreferences(preferences)

但是,您可能希望使属性类型可为 null,就好像您的 SharedPreferences 不包含该值一样,这会在访问该值时引发异常。

关于generics - 如何使用泛型获取枚举的值?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53563449/

相关文章:

delphi - delphi 中的 std::multimap 等效项

强制兼容通配符的 Java 泛型

Kotlin - 如何在构建器 block 内迭代 map 或列表

java - 在返回所述接口(interface)的通用接口(interface)中创建静态变量(或者至少在 Spring 的映射器中)

java - 如何实现List<SomeParamType>到List<SomeParamType<?>>的转换

generics - kotlin - 删除类属性中的可为空性

java - MongoDB getList ("field-name", Double::class.java);在 Kotlin 中产生 ClassCastException

Kotlin supplyAsync with executor

android - 资源$NotFoundException : Unable to find resource ID #0xffffffff using NestedScrollView with Motionlayout

spring - 如何在gradle中获取依赖项的元数据?