повторное использование логики в приостанавливаемых и неподдерживаемых функциях

#kotlin

#kotlin

Вопрос:

Следующие два метода содержат одинаковую функциональность, единственное отличие состоит в том, что один приостанавливаемый, а другой нет (то же самое для параметров).

Как я могу извлечь реализацию и повторно использовать ее для обеих функций?

 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
    }
}
 

Я мог бы сохранить только приостанавливаемую функцию, но это означало бы, что я должен использовать a runBlocking каждый раз, когда я ее использую.

Ответ №1:

Сохраните версию без приостановки и создайте ее inline . Это решает проблему, поскольку встроенный лямбда-выражение может содержать приостанавливающие вызовы, не будучи объявленным suspend само по себе. Именно так это делает большинство стандартных библиотек Kotlin ( forEach , map , и т.д.):

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

 

Кроме того, это обычно полезно для функций более высокого порядка, которые принимают лямбда-выражения для объявления inline , поскольку это позволяет избежать дополнительных затрат на экземпляры лямбда.