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

Ada*_*331 3 generics kotlin

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

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)
Run Code Online (Sandbox Code Playgroud)

但是,我希望我可以使用泛型枚举,因为所有枚举都有一个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)
Run Code Online (Sandbox Code Playgroud)

这样的事情可能吗?

kco*_*ock 6

根据您的答案,您可以避免使用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()
    }
}
Run Code Online (Sandbox Code Playgroud)

然后您可以使用以下方法轻松添加委托:

inline fun <reified T : Enum<T>> sharedPreferences(prefs: SharedPreferences) = 
    SharedPrefsEnum(prefs, T::class.java)
Run Code Online (Sandbox Code Playgroud)

允许您为其分配:

private var myEnum: MyEnum by sharedPreferences(preferences)
Run Code Online (Sandbox Code Playgroud)

您可能希望将属性类型设置为可为空,但是,如果您SharedPreferences不包含值,则在访问该值时会抛出异常.

  • 哇!谢谢!很快就会尝试这个. (2认同)