Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/kotlin/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
Kotlin 如何制作吞咽异常的函数 inline fun rest(请求:()->T):T=try{ 请求() }catch(e:HttpException){ val requestId=e.response().raw().request().header(request\u ID\u header) if(requestId!=null){ 对话框(requestId,R.string.oops).show(fragmentManager,null) }否则{ 掷e } }_Kotlin - Fatal编程技术网

Kotlin 如何制作吞咽异常的函数 inline fun rest(请求:()->T):T=try{ 请求() }catch(e:HttpException){ val requestId=e.response().raw().request().header(request\u ID\u header) if(requestId!=null){ 对话框(requestId,R.string.oops).show(fragmentManager,null) }否则{ 掷e } }

Kotlin 如何制作吞咽异常的函数 inline fun rest(请求:()->T):T=try{ 请求() }catch(e:HttpException){ val requestId=e.response().raw().request().header(request\u ID\u header) if(requestId!=null){ 对话框(requestId,R.string.oops).show(fragmentManager,null) }否则{ 掷e } },kotlin,Kotlin,它应该执行一些REST请求(在请求参数中),如果失败,并且包含指定的HTTP头,则显示带有该头的对话框 但是编译器在带有对话框的行中抱怨它没有返回t,而是返回Unit。但这就是我想要的!我该怎么做 我想到的一个解决方案是将函数的返回类型设置为T?并返回null,但在Kotlin中这样做感觉很脏。您可以通过泛型结果类型来解决它: inline fun <T> rest(request: () -> T): T = try { request() } catch (e: H

它应该执行一些REST请求(在
请求
参数中),如果失败,并且包含指定的HTTP头,则显示带有该头的对话框

但是编译器在带有对话框的行中抱怨它没有返回
t
,而是返回
Unit
。但这就是我想要的!我该怎么做


我想到的一个解决方案是将函数的返回类型设置为
T?
并返回
null
,但在Kotlin中这样做感觉很脏。

您可以通过泛型
结果
类型来解决它:

inline fun <T> rest(request: () -> T): T = try {
    request()
} catch (e: HttpException) {
    val requestId = e.response().raw().request().header(REQUEST_ID_HEADER) 
    if (requestId != null) {
        Dialog(requestId, R.string.oops).show(fragmentManager, null)
    } else {
        throw e
    }
}
密封类结果{
类成功(val值:T):结果()
类错误(val异常:异常,val请求ID:字符串?):结果()
}
内联有趣的休息(请求:()->T):结果=尝试{
Result.Success(请求())
}catch(e:HttpException){
val requestId=e.response().raw().request().header(request\u ID\u header)
结果.错误(e,请求ID)
}
私人娱乐测试{
val result=rest(::testRequest)
何时(结果){
是Result.Success->Log.v(“调试”,“成功:${Result.value}”)
是结果。错误->{
result.requestId?.let{
对话框(it,R.string.oops).show(fragmentManager,null)
}?:运行{
抛出result.exception
}
}
}
}
返回空值。使用null有时会被滥用,但这是使用null的一个非常有效的用例。 Kotlin允许您以安全和友好的方式使用null,所以不要害怕使用它

另一个选项是在显示对话框的情况下也抛出异常(无论标题是否存在)

为了进行选择,您必须问问自己,如果显示对话框,调用
rest()
的代码将做什么。它必须以某种方式处理
T
的缺失(null或异常)。这是因为显示对话框并不是结束函数执行的事情

最后但并非最不重要的一点是,在
rest()
方法之外还有一个处理结果的选项。改进塔拉斯的答案:

sealed class Result<out T : Any> {
    class Success<out T : Any>(val value: T) : Result<T>()
    class Error(val exception: Exception, val requestId: String?) : Result<Nothing>()
}

inline fun <T : Any> rest(request: () -> T): Result<T> = try {
    Result.Success(request())
} catch (e: HttpException) {
    val requestId = e.response().raw().request().header(REQUEST_ID_HEADER)
    Result.Error(e, requestId)
}

private fun testRest() {
    val result = rest(::testRequest)
    when (result) {
        is Result.Success -> Log.v("__DEBUG", "success: ${result.value}")
        is Result.Error -> {
            result.requestId?.let {
                Dialog(it, R.string.oops).show(fragmentManager, null)
            } ?: run {
                throw result.exception
            }
        }
    }
}
密封类结果{
类成功(val值:T):结果()
类ErrorWithId(val异常:异常,val请求ID:字符串):结果()
类错误(val异常:异常):结果()
}
内联有趣的休息(请求:()->T):结果=尝试{
Result.Success(请求())
}catch(e:HttpException){
val requestId=e.response().raw().request().header(request\u ID\u header)
if(requestId!=null){
结果.可恢复错误(e,requestId)
}否则{
结果.错误(e)
}
}
私人娱乐项目Callingrest(){
val result=rest(::testRequest)
何时(结果){
是Result.Success->Log.v(“调试”,“成功:${Result.value}”)
is Result.ErrorWithId->Dialog(Result.requestId,R.string.oops).show(fragmentManager,null)
是Result.Error->throw Result.exception
}
}

返回null一开始可能感觉很难看,但有什么选择呢

选项1:引发异常

如果您需要关于代码失败原因的更多信息,您应该抛出一个异常

让我们以Kotlin的函数为例:

sealed class Result<out T : Any> {
    class Success<out T : Any>(val value: T) : Result<T>()
    class ErrorWithId(val exception: Exception, val requestId: String) : Result<Nothing>()
    class Error(val exception: Exception) : Result<Nothing>()
}

inline fun <T : Any> rest(request: () -> T): Result<T> = try {
    Result.Success(request())
} catch (e: HttpException) {
    val requestId = e.response().raw().request().header(REQUEST_ID_HEADER)
    if (requestId != null) {
        Result.RecoverableError(e, requestId)
    } else {
        Result.Error(e)
    }
}

private fun thingCallingRest() {
    val result = rest(::testRequest)
    when (result) {
        is Result.Success -> Log.v("__DEBUG", "success: ${result.value}")
        is Result.ErrorWithId -> Dialog(result.requestId, R.string.oops).show(fragmentManager, null)
        is Result.Error -> throw result.exception
    }
}

使用elvis操作符提供回退也是非常简洁的:

listOf<Int>().singleOrNull() // returns null
listOf().singleOrNull()?:1//默认元素

如果在任何情况下都不返回t,为什么返回类型是t?您应该决定返回
null
或抛出异常以向调用方代码报告任何问题。现在,您尝试混合这两种方法调用
Dialog.show
时,返回值应该是什么?如果在此场景中
rest
不返回任何内容,则其返回类型应为
T?
,并且您的代码在
show
调用后应返回
null
。但是客户端代码应该使用符号来访问返回值,不是吗?您必须问问自己,如果显示对话框,调用
rest()
的代码将做什么。它必须以某种方式处理T的缺失(异常或空值),因为它不会接收到T的实例。结果的使用者在这里看起来很复杂,为什么不一直单独处理这3种情况呢?我试着在我的答案中改进你的答案。同意,它看起来更干净
listOf<Int>(1, 1).single { it == 1 } 
listOf<Int>().singleOrNull() // returns null
listOf<Int>().singleOrNull() ?: 1 // default element