Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/sqlite/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Generics Kotlin扩展泛型函数,基本类型不带反射API_Generics_Kotlin_Kotlin Extension - Fatal编程技术网

Generics Kotlin扩展泛型函数,基本类型不带反射API

Generics Kotlin扩展泛型函数,基本类型不带反射API,generics,kotlin,kotlin-extension,Generics,Kotlin,Kotlin Extension,我有一个Java对象,它有getLong、getBoolean和getString方法。我试图创建一个通用扩展函数,该函数的最后一个参数是函数。本质上是包装try-and-catch和对getString等的调用,这些调用可能引发异常。我发现当调用例如getIt{//dosomething with it}时,as set需要反射api来计算T。我不能做的是检查或isInstance。有什么想法吗 // This is the non generic function version to ge

我有一个Java对象,它有getLong、getBoolean和getString方法。我试图创建一个通用扩展函数,该函数的最后一个参数是函数。本质上是包装try-and-catch和对getString等的调用,这些调用可能引发异常。我发现当调用例如getIt{//dosomething with it}时,as set需要反射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)
    }
}
下面的选项不起作用

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)
    }
}
与jsonObj.getIterror、JSONObject::getString{err=it}相比,这看起来像是jsonObj.getIterror{er=it}

更新2:至少对我来说,这似乎最终是一个更好的方法,避免了使用泛型来实现目标的问题

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") }
kotlin is操作符在左侧获取一个对象,在右侧获取一个类引用。您只需使用一个简单的相等性检查即可,因为两侧都有类引用

T在编译时仍然是未知的,所以将这个.get*作为T没有多大意义。您已经在when块中验证了该类型,因此不妨使用它

作为完整性问题,您可能还需要包含一个else块,以防有人调用jsonObject.getIt

我还包括了第二个版本,它需要调用一个额外的参数,但听起来像是您最初想要的不太详细的版本。它接受密钥、访问器和块,并对将来添加到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)
    }
}

请发布你的课程来指出你的问题。我更新了示例代码,希望这有助于@nickrack的回答。第二个解决方案可以工作,但需要访问器,它重复指示类型。第一个解决方案不适用于when。感谢您的回复。但是,top未运行,应为@ParameterName T。。。所以把它改成T,然后至少在Android上运行这段代码是行不通的。当lambda从未被执行时。我在里面放了一个else,它就被执行了。带有访问器的第二个版本可以工作。
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)
    }
}