我有一个包含方法getLong
,getBoolean
和getString
的Java对象。我试图创建一个具有函数作为最后一个参数的通用扩展函数。基本上包装try和catch并调用可能引发异常的getString
等。我发现在调用示例<reified T>
时设置的getIt<Long>() { // do something with it }
需要反射api才能找出T
。我不能做的是检查也不是isInstance。有什么想法吗?
// This is the non generic function version to get an idea
inline fun JSONObject.getItLong(key: String, block: (value: Long) -> Unit) {
try {
block(this.getLong(key))
} catch (e: JSONException) {
Log.w("${ javaClass.simpleName }KEx", e.message)
}
}
以下when
不起作用。
inline fun <reified T> JSONObject.getIt(key: String, block: (value: T) -> Unit) {
try {
when {
Long is T -> { block(this.getLong(key) as T) }
String is T -> { block(this.getString(key) as T) }
// Boolean is T -> { block(this.getBoolean(key) as T) } // Boolean broken, does not have companion object?
}
} catch (e: JSONException) {
Log.w("fetchFromJSONObject", e.message)
}
}
因此,除了布尔问题之外,我想通过使用T
来使用通用的方法来调用正确的get类型。我遇到需要将kaitlin反射jar添加到类路径中。我希望尽可能避免这种情况。
UPDATE1:使用when
和T::class
的第一个答案和回复实际上无效。谢谢你的想法,它帮我看了一遍。第二个我发现&#34;更多&#34;比我想要的更多,所以我最终得到了这个解决方案。
inline fun <reified T> JSONObject.getIt(key: String, block: (value: T) -> Unit) {
try {
block(this.get(key) as T)
} catch (e: JSONException) {
Log.w("${ javaClass.simpleName }KEx", e.message)
}
}
与jsonObj.getIt<String>("error") { er = it }
jsonObj.getIt<String>("error", JSONObject::getString) { err = it }
UPDATE2:这似乎最终是一种更好的方法,至少对我而言,避免了使用泛型来实现目标的问题
inline fun JSONObject.unless(func: JSONObject.() -> Unit) {
try {
this.func()
} catch (e: JSONException) {
Log.w("${ javaClass.simpleName }KEx", e.message)
}
}
使用:
jsonObj.unless {
sDelay = getLong("s_delay") * 1000
wDelay = getLong("w_delay") * 1000
}
jsonObj.unless { sam = getBoolean("sam") }
jsonObj.unless { err = getString("error") }
答案 0 :(得分:1)
kotlin is
运算符在左侧获取一个对象,在右侧获取一个类引用。你可以在那里使用简单的相等检查,因为你已经在两边都有类引用。
T在编译时仍然是未知的,因此使用this.get*() as T
并没有多大意义。你已经验证了你的阻止时的类型,所以你也可以使用它。
作为完整性问题,您可能还希望在有人拨打jsonObject.getIt<Date>(...)
时添加其他阻止。
我还包含了第二个版本,它需要一个额外的参数来调用,但听起来像是你原本想要的一个不那么详细的版本。它需要key
,accessor
和block
,并且适用于将来添加到JSONObject
的任何现有和新访问者,而无需对扩展进行任何修改或修改。
inline fun <reified T> JSONObject.getIt(key: String, block: (value: T) -> Unit) {
try {
when (T::class) {
kotlin.Long::class -> block(this.getLong(key) as Long)
kotlin.String::class -> block(this.getString(key) as String)
kotlin.Boolean::class -> block(this.getBoolean(key) as Boolean)
}
} catch (e: JSONException) {
Log.w("fetchFromJSONObject", e.message)
}
}
inline fun <T> JSONObject.getIt(key: String, accessor: JSONObject.(String) -> T, block: (T) -> Unit) {
try {
accessor(key).let(block)
} catch (e: JSONException) {
Log.w("fetchFromJSONObject", e.message)
}
}