在Kotlin中使用高阶函数在try catch中包装函数



我有一组函数,它们有不同的签名和参数,但它们都可能抛出异常。我想写一个内联函数,它接受一个函数作为参数,并在try-catch块中调用该函数,返回包含异常的特定类型,而不是在每个函数中都添加try-catch。


// first function. 
fun foo() -> String
// second function. 
fun bar(argument: String) -> Boolean

// Result Type
sealed class Result<out R> {
data class Success<out T>(val data: T) : Result<T>()
data class Error(val exception: Exception) : Result<Nothing>()
}
// Wrapper Function
inline fun <T, R> safeCall(call: (T) -> R): Result<R>

// This Returns Result<String>
safeCall { 
foo()
}
// This Returns Result<Boolean>
safeCall { 
bar()
}

我在实现safeCall()方法时面临一个问题。理想情况下,我希望这对任何底层函数都有效。我可以让它为foo()bar(argument: String)工作,但不能同时为两者工作。

inline fun <T, R> safeCall(
call: (T) -> R, // This syntax forces to to have only one parameter.
): Result<R> {
return try {
val result: R = call() // This throws compilation error. 
Result.Success(result)
} catch (e: Exception) {
Result.Error(e)
}
}

PS -很新的Kotlin和函数式编程。

当然!这听起来像是一个合理的设计模式。只是一些注意事项。

inline fun <T, R> safeCall(call: (T) -> R): Result<R>

safeCall的论证本身不需要论证。它只是我们将要调用的一段代码,所以这将是一个更合适的签名。

inline fun <R> safeCall(call: () -> R): Result<R>

现在,至于如何实际实现它,听起来你有所有正确的想法。请尝试在实际的Kotlintry块中调用该函数。

inline fun <R> safeCall(call: () -> R): Result<R> {
try {
return Result.Success(call())
} catch (e: Exception) {
return Result.Error(e)
}
}

你可以把它命名为

safeCall { 
foo()
}
safeCall { 
bar("Example Argument")
}

请记住,bar接受一个参数。即使该参数是在safeCall作用域之外定义的,它仍然可以通过闭包的魔力来工作。

val x = "This works :)"
safeCall { 
bar(x)
}

通过实现您的Result类,您似乎真的从stdlib中复制了一个名为…那么,Result:-)您的safeCall则命名为runCatching:

// Result<String>
runCatching {
foo()
}
// Result<Boolean>
runCatching {
bar("Example Argument")
}

最新更新