Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/kotlin/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Generics 如何使用泛型获取枚举的值?_Generics_Kotlin - Fatal编程技术网

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

Generics 如何使用泛型获取枚举的值?,generics,kotlin,Generics,Kotlin,我想提供这个问题的背景。我见过一些独特的解决方案,其中人们创建的委托将从SharedReference而不是支持字段进行读/写。要对字符串执行此操作,例如: class SharedPrefsString(private val sharedPrefs: SharedPreferences) { operator fun getValue(thisRef: Any?, property: KProperty<*>): String { return share

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

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)
这样的事情可能吗

我正在使用这个:

var lastUpdate by PersistedProperty("lastUpdate",0L)
这就是实现:

class PersistedProperty<T>(var prefName:String, var default: T)
{
    operator fun getValue(thisRef: Any?, property: KProperty<*>): T {
        return value!!
    }

    operator fun setValue(thisRef: Any?, property: KProperty<*>, value: T){
        this.value=value
    }

    fun getFresh():T
    {
        value = getPreference(prefName, default)
        return value!!
    }

    var value:T? = null
        get(){
            if(field==null)
                field=getPreference(prefName, default)
            return field
        }
        set(value){
            if(value==field)
                return
            savePreference(prefName, value)
            field=value
        }

}

fun<T> savePreference(name:String, value:T,prefFile: String? = null)
{
    val sharedPreferences = App.instance.getSharedPreferences(prefFile?:App.instance.packageName+ "_preferences",Context.MODE_PRIVATE)
    when(value)
    {
        is String->sharedPreferences.edit().putString(name, value).apply()
        is Int->sharedPreferences.edit().putInt(name, value).apply()
        is Long->sharedPreferences.edit().putLong(name, value).apply()
        is Float->sharedPreferences.edit().putFloat(name, value).apply()
        is Boolean->sharedPreferences.edit().putBoolean(name, value).apply()
        else -> throw(Exception("Not suported type"))
    }
}
class PersistedProperty(变量prefName:String,变量默认值:T)
{
运算符fun getValue(thisRef:Any?,属性:KProperty):T{
返回值!!
}
运算符fun setValue(thisRef:Any?,属性:KProperty,值:T){
这个。值=值
}
fun getFresh():T
{
value=getPreference(prefName,默认值)
返回值!!
}
变量值:T?=null
得到(){
如果(字段==null)
field=getPreference(prefName,默认值)
返回场
}
设置(值){
如果(值==字段)
返回
保存首选项(prefName、value)
字段=值
}
}
fun savePreference(名称:String,值:T,预文件:String?=null)
{
val SharedReferences=App.instance.getSharedReferences(prefFile?:App.instance.packageName+“_首选项”,Context.MODE_PRIVATE)
何时(值)
{
is String->sharedReferences.edit().putString(名称、值).apply()
is Int->SharedReferences.edit().putInt(名称、值).apply()
is Long->sharedReferences.edit().putLong(名称、值).apply()
是Float->SharedReferences.edit().putFloat(名称、值).apply()
is Boolean->sharedPreferences.edit().putBoolean(名称、值).apply()
else->throw(异常(“非支持类型”))
}
}

我能够通过反射解决这个问题。谢谢佐伊为我指明了正确的方向

我也必须为enum传入类,但使用该类,我可以使用反射查找
valueOf
,并使用从首选项中获得的字符串调用它

class SharedPrefsEnum<T : Enum<T>>(private val sharedPrefs: SharedPreferences, private val clazz: Class<T>) {
    operator fun getValue(thisRef: Any?, property: KProperty<*>): T {
        val prefsString = sharedPrefs.getString(property.name, "")
        val method = clazz.getDeclaredMethod("valueOf", String::class.java)
        return method.invoke(null, prefsString) as T
    }

    operator fun setValue(thisRef: Any?, property: KProperty<*>, value: T) {
        sharedPrefs.edit().putString(property.name, value.name).apply()
    }
}
class SharedReference(私有val SharedReferences:SharedReferences,私有val clazz:class){
运算符fun getValue(thisRef:Any?,属性:KProperty):T{
val prefsString=sharedPrefs.getString(property.name,“”)
val方法=clazz.getDeclaredMethod(“valueOf”,String::class.java)
return method.invoke(null,prefsString)作为T
}
运算符fun setValue(thisRef:Any?,属性:KProperty,值:T){
sharedPrefs.edit().putString(property.name,value.name).apply()
}
}

基于您的答案,您可以使用
枚举常量
属性避免使用反射:

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

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

您可能需要获取一个
Class
KClass
。但是,不支持具体化的类级泛型,因此必须手动执行。也许有更好的办法though@Zoe一旦我有了课堂参考,我能做什么?弄清楚如何使用反射调用“valueOf”?IIRC,
valueOf
是静态的,因此您可以尝试使用反射获取方法,然后调用它。对于
KClass
,这应该是非常简单的,但是您可能会得到一个SecurityException。我没有太多接触反射,所以我不熟悉如何正确避免反射those@Zoe谢谢你为我指明了正确的方向。:)这是非常相似的,但不幸的是,我不认为这将有助于枚举。哇!谢谢稍后将尝试此操作。对
getValue
中的val进行了一些小调整,以避免多次获取val
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()
    }
}
inline fun <reified T : Enum<T>> sharedPreferences(prefs: SharedPreferences) = 
    SharedPrefsEnum(prefs, T::class.java)
private var myEnum: MyEnum by sharedPreferences(preferences)