Reputation: 9187
I want to take advantage of kotlin's when expressions and generic methods to simplify shared preferences api of Android.
Instead of calling getString() & getInt() etc. all the time, What I want to do is to create an extension function that would switch based on return type of function and call appropriate method. Something like below :
fun <T> SharedPreferences.get(key: String): T? {
when (T) { //how do I switch on return type and call appropriate function?
is String -> getString(key, null)
is Int -> getInt(key, -1)
is Boolean -> getBoolean(key, false)
is Float -> getFloat(key, -1f)
is Long -> getLong(key, -1)
}
return null
}
Of Course, it will not work. But is there any solution to use when expression for return type of a function? All suggestions are welcome.
Upvotes: 11
Views: 2808
Reputation: 147951
To achieve exactly what you want, you can use reified type parameters. This will make the compiler inline your function at its call sites with T
replaced with the type used at the call site.
The function would look like:
@Suppress("IMPLICIT_CAST_TO_ANY")
inline operator fun <reified T> SharedPreferences.get(key: String): T? =
when (T::class) {
String::class -> getString(key, null)
Int::class -> getInt(key, -1)
Boolean::class -> getBoolean(key, false)
Float::class -> getFloat(key, -1f)
Long::class -> getLong(key, -1)
else -> null
} as T?
If you make get
an operator
function, you can also call it using the operator syntax: prefs[name]
.
The calls should, of course, provide enough type information for the compiler to infer T
:
val i: Int? = prefs["i"] // OK, the type information is taken from the declaration
val j: Int = prefs["i"]!! // OK
val x = prefs["x"] // Error, not enough type information
val y = prefs.get<String>("y") // OK, the type will be `String?`
fun f(z: Int) = z
f(prefs["z"]!!) // OK, the type information is taken from the parameter type
Upvotes: 11