我正在嘗試使用 Kotlin 中的委托屬性為持久保存到非型別存盤的應用程式首選項提供一些型別安全性。store 在語意上有點像某種型別的Map<String,Any>,盡管它沒有實作那個特定的類。
我遇到的問題是,單個委托類似乎不可能實作,并且不能實作getValue多種setValue型別。
如果這是SomePreferences其他應用程式呼叫 get/setpreferenceOne和的型別安全類preferenceTwo:
class SomePreferences {
private val myDelegate = MyPreferenceStorageImpl()
var preferenceOne: Boolean by myDelegate
var preferenceTwo: String by myDelegate
}
但是,如果我嘗試創建MyPreferencesStorageImpl,它會嘗試看起來像這樣:
class MyPreferenceStorageImpl() {
operator fun getValue(somePreferences: SomePreferences, property: KProperty<*>): Boolean {
TODO("Read from underlying store, transforming the read value as a boolean")
}
operator fun setValue(somePreferences: SomePreferences, property: KProperty<*>, b: Boolean) {
TODO("Write to underlying store, transforming the value from a Boolean")
}
operator fun getValue(somePreferences: SomePreferences, property: KProperty<*>): String {
TODO("Read from underlying store, transforming value to a String")
}
operator fun setValue(somePreferences: SomePreferences, property: KProperty<*>, s: String) {
TODO("Write to underlying store, transforming given value to a string")
}
}
但是,這不起作用,因為我有兩種方法,它們僅在回傳型別上有所不同,這是一個沖突。
我有幾個關于如何解決這個問題的半生不熟的想法,包括嘗試以Map<String, Any>某種方式進行子類化,或者可能為每個偏好型別(ew)或泛型(不知何故)提供特定于型別的實作,但這些感覺不特別正確。
我在這里錯過了一個明顯更好的方法嗎?
uj5u.com熱心網友回復:
假設您不會在具有型別引數的屬性上使用委托作為其型別...
您可以使其通用:
class MyPreferenceStorageImpl() {
operator fun <T> getValue(somePreferences: SomePreferences, property: KProperty<*>): T {
TODO("Read from underlying store, transforming the read value as a T")
}
operator fun <T> setValue(somePreferences: SomePreferences, property: KProperty<*>, b: T) {
TODO("Write to underlying store, transforming the value from a T")
}
}
請注意,當您從 回來時getValue,您需要進行未經檢查的演員表。這不可能是 100% 安全的,因為T可能有自己的型別引數。您至少可以檢查以下內容:
// suppose you've got the value from storage and it's now stored in "returnValue"
if ((property.returnType.classifier as? KClass<*>)?.isInstance(returnValue) == true) {
return returnValue as T
} else {
// something went wrong, returnValue is not an instance of T
}
如果您需要以不同方式處理每種型別 ( String, Int, Boolean),您可以執行以下操作:
when (property.returnType) {
typeOf<String>() -> TODO()
typeOf<Int>() -> TODO()
typeOf<Boolean>() -> TODO()
else -> throw UnsupportedOperationException()
}
uj5u.com熱心網友回復:
如果您想在沒有反射庫的情況下執行此操作,則可以使用具體型別。
class MyPreferenceStorageImpl {
inline operator fun <reified T> getValue(somePreferences: SomePreferences, property: KProperty<*>): T {
when (T::class) {
Boolean::class -> TODO("Read from underlying store, transforming the read value as a Boolean")
String::class -> TODO("Read from underlying store, transforming the read value as a String")
else -> error("${T::class} is an unsupported property type for delegation.")
}
}
inline operator fun <reified T> setValue(somePreferences: SomePreferences, property: KProperty<*>, value: T) {
when (T::class) {
Boolean::class -> TODO("Write to underlying store, transforming the value from a Boolean")
String::class -> TODO("Write to underlying store, transforming the value from a String")
else -> error("${T::class} is an unsupported property type for delegation.")
}
}
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/529186.html
標籤:科特林代表
