首页 > 解决方案 > 在可暂停和不可暂停函数中重用逻辑

问题描述

以下两种方法包含相同的功能,唯一的区别是一种是可挂起的,另一种不是(参数相同)。

如何提取实现并将其用于这两个功能?

fun validationWrapper(supplier: () -> Unit) = try {
    supplier.invoke()
} catch (ex: Exception) {
    when (ex) {
        is IllegalArgumentException, is IllegalStateException -> throw ValidationException(ex.message!!)
        else -> throw ex
    }
}

suspend fun validationWrapper(supplier: suspend () -> Unit) = try {
    supplier.invoke()
} catch (ex: Exception) {
    when (ex) {
        is IllegalArgumentException, is IllegalStateException -> throw ValidationException(ex.message!!)
        else -> throw ex
    }
}

我只能保留可挂起的功能,但这意味着我runBlocking每次使用它时都应该使用它。

标签: kotlin

解决方案


Keep the non-suspend version and make it inline. This solves the problem because the inlined lambda can then contain suspending calls without being declared suspend itself. It is how most of the Kotlin stdlib does this (forEach, map, etc.):

inline fun validationWrapper(supplier: () -> Unit) = try {
    supplier.invoke()
} catch (ex: Exception) {
    when (ex) {
        is IllegalArgumentException, is IllegalStateException -> throw ValidationException(ex.message!!)
        else -> throw ex
    }
}

Also, it is generally useful for higher-order functions that take lambdas to be declared inline, because it avoids extra costs of lambda instances.


推荐阅读