我有一组函数,它们有不同的签名和参数,但它们都可能抛出异常。我想写一个内联函数,它接受一个函数作为参数,并在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")
}