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