Exception 科特林:捕获扩展

Exception 科特林:捕获扩展,exception,exception-handling,kotlin,Exception,Exception Handling,Kotlin,因为Kotlin不像java那样支持多个catch,所以我想创建扩展来部分解决这个问题 fun <T: Throwable> (() -> Unit).catch(vararg exceptions: KClass<T>, catchBlock: (Throwable) -> Unit) { try { this() } catch (e: Throwable) { if (e::class in except

因为Kotlin不像java那样支持多个
catch
,所以我想创建扩展来部分解决这个问题

fun <T: Throwable>  (() -> Unit).catch(vararg exceptions: KClass<T>, catchBlock: (Throwable) -> Unit) {
    try {
        this()
    } catch (e: Throwable) {
        if (e::class in exceptions) catchBlock(e) else throw e
    }
}
但问题是,如果要传递多个具有不同类型的参数,它将不起作用(类型推断失败):


那么,如何更改扩展的签名以捕获不同类型的几个异常呢?

让我们看看您试图传递给函数的两个片段的类型:

val kclass1: KClass<NotImplementedException> = NotImplementedException::class
val kclass2: KClass<IndexOutOfBoundsException> = IndexOutOfBoundsException::class
但真正的解决方案是使用
out
关键字为
KClass
实例的类型参数指定:

fun <T : Throwable> (() -> Unit).catch(vararg exceptions: KClass<out T>, catchBlock: (Throwable) -> Unit) {
    try {
        this()
    } catch (e: Throwable) {
        if (e::class in exceptions) catchBlock(e) else throw e
    }
}

让我们看看您试图传递给函数的两个Arumging的类型:

val kclass1: KClass<NotImplementedException> = NotImplementedException::class
val kclass2: KClass<IndexOutOfBoundsException> = IndexOutOfBoundsException::class
但真正的解决方案是使用
out
关键字为
KClass
实例的类型参数指定:

fun <T : Throwable> (() -> Unit).catch(vararg exceptions: KClass<out T>, catchBlock: (Throwable) -> Unit) {
    try {
        this()
    } catch (e: Throwable) {
        if (e::class in exceptions) catchBlock(e) else throw e
    }
}

次要细节:您的版本只在类完全匹配时捕获,但它也应该覆盖子类。当然,OP也有同样的问题。次要细节:您的版本只在类完全匹配时捕获,但它也应该覆盖子类。当然,OP也有同样的问题。
fun <T : Throwable> (() -> Unit).catch(vararg exceptions: KClass<out T>, catchBlock: (Throwable) -> Unit) {
    try {
        this()
    } catch (e: Throwable) {
        if (e::class in exceptions) catchBlock(e) else throw e
    }
}
{
    throw IndexOutOfBoundsException()
}.catch<RuntimeException>(NotImplementedException::class, IndexOutOfBoundsException::class) {
    println("Caught something: $it")
}