由于我的api调用,我使用ResultWrapper
如下:
sealed class ResultWrapper<out T> {
data class Success<T>(val data: T) : ResultWrapper<T>()
data class Unauthorized<T>(val exception: UnauthorizedException) : ResultWrapper<T>()
//More error classes
}
使用ResultWrapper.
时,我无法获得T:
when(function) {
is ResultWrapper.Success -> DoSomething
is ResultWrapper.SomeError -> DoSomething
我意识到我无法使用它的返回值,所以我找到了这个密封的类
sealed class Either<out L, out R> {
//Failure
data class Left<out L>(val value: L) : Either<L, Nothing>()
//Success
data class Right<out R>(val value: R) : Either<Nothing, R>()
val isRight get() = this is Right<R>
val isLeft get() = this is Left<L>
fun <L> left(a: L) = Left(a)
fun <R> right(b: R) = Right(b)
}
fun <L, R, T> Either<L, R>.fold(left: (L) -> T, right: (R) -> T): T =
when (this) {
is Either.Left -> left(value)
is Either.Right -> right(value)
}
fun <L, R, T> Either<L, R>.flatMap(f: (R) -> Either<L, T>): Either<L, T> =
fold({ this as Either.Left }, f)
fun <L, R, T> Either<L, R>.map(f: (R) -> T): Either<L, T> =
flatMap { Either.Right(f(it)) }
有了这个我就可以做到,事情是我正在使用它:
inline fun <reified T : Any> execute(requestFunc: () -> T): ResultWrapper<T> =
try {
ResultWrapper.Success(requestFunc.invoke())
} catch (exception: Exception) {
when (exception) {
is UnauthorizedException -> ResultWrapper.Unauthorized(exception)
is NetworkException -> ResultWrapper.Network(exception)
is BadRequestException -> ResultWrapper.BadRequest(exception)
is NotFoundException -> ResultWrapper.NotFound(exception)
else -> ResultWrapper.Error(exception)
}
}
然后尝试将其移动到Either
时遇到了问题,因为我必须执行类似reified T,R
的操作,返回值是Either<T,R>
,但随后尝试执行{{1} }表示期望T,R,而我只返回T。
有什么想法要实现吗?
我知道如何使用Either.Right(requestFunc.invoke())
,但是我想知道如何使用ResultWrapper
,所以我可以使用Either
并获得两个结果。
我这样做的方法是使用:
fold()
答案 0 :(得分:0)
因此,您想使用Either<L, R>
。然后,您需要为成功的结果指定类型(可以仅为T
),为失败的类型指定。对于后者,如果您需要区分不同类型的失败,您仍然必须引入类似密封类的东西:
sealed class Failure(val cause: Exception) {
class Unauthorized(cause: Exception) : Failure(cause)
class Network(cause: Exception) : Failure(cause)
class BadRequest(cause: Exception) : Failure(cause)
class NotFound(cause: Exception) : Failure(cause)
class Error(cause: Exception) : Failure(cause)
}
然后您可以实现execute
来以这种方式返回Either
:
inline fun <reified T : Any> execute(requestFunc: () -> T): Either<Failure, T> =
try {
Either.Right(requestFunc.invoke())
} catch (exception: Exception) {
Either.Left(when (exception) {
is UnauthorizedException -> Failure.Unauthorized(exception)
is NetworkException -> Failure.Network(exception)
is BadRequestException -> Failure.BadRequest(exception)
is NotFoundException -> Failure.NotFound(exception)
else -> Failure.Error(exception)
})
}
通常,代表成功结果的类型用作R
类型参数或Either<L, R>
,失败类型用作L
。