0

我有一个具有方法的 Java 对象getLonggetBoolean并且getString. 我试图制作一个通用扩展函数,它有一个函数作为最后一个参数。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)
    }
}

因此,除了布尔问题之外,我还希望有一种通用的方式来调用正确类型的 get 通过使用T. 我遇到需要将 kaitlin 反射 jar 添加到类路径中。如果可能的话,我想避免这种情况。

UPDATE1:使用whenwith的第一个答案和响应T::class实际上不起作用。感谢您的想法,它帮助我重新审视。第二个我发现比我想要的更“冗长”,所以我最终得到了这个解决方案。

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") }
4

1 回答 1

1

kotlinis运算符在左侧获取一个对象,在右侧获取一个类引用。您可以在那里使用简单的相等性检查,因为您已经在两边都有类引用。

T 在编译时仍然是未知的,因此采用this.get*() as T并没有多大意义。您已经验证了 when 块中的类型,因此您不妨使用它。

为了完整起见,您可能还想包含一个 else 块,以防有人调用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)
    }
}
于 2017-07-22T00:07:47.860 回答