在 Kotlin 中使用高阶函数在 try catch 中包装一个函数
Wrap a function in try catch using Higher order functions in Kotlin
我有一组具有不同签名和参数的函数,但它们都可能引发异常。我不想在它们中的每一个中添加 try-catch,而是想编写一个内联函数,它将一个函数作为参数并在 try-catch 块中调用该函数,并且 returns 是包装异常的某些类型。
// 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>
现在至于如何实际实施它,听起来您的想法是正确的。只需尝试在实际的 Kotlin try
块中调用该函数。
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
class 你真的似乎从 stdlib 中复制了一个 class 命名...好吧,Result
:-) 你的 safeCall
然后命名为 runCatching
:
// Result<String>
runCatching {
foo()
}
// Result<Boolean>
runCatching {
bar("Example Argument")
}
我有一组具有不同签名和参数的函数,但它们都可能引发异常。我不想在它们中的每一个中添加 try-catch,而是想编写一个内联函数,它将一个函数作为参数并在 try-catch 块中调用该函数,并且 returns 是包装异常的某些类型。
// 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>
现在至于如何实际实施它,听起来您的想法是正确的。只需尝试在实际的 Kotlin try
块中调用该函数。
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
class 你真的似乎从 stdlib 中复制了一个 class 命名...好吧,Result
:-) 你的 safeCall
然后命名为 runCatching
:
// Result<String>
runCatching {
foo()
}
// Result<Boolean>
runCatching {
bar("Example Argument")
}