Преобразование возврата дооснащения в Либо - PullRequest
0 голосов
/ 24 октября 2019

Я использовал ResultWrapper в результате моего вызова API следующим образом:

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
}

Я не мог получить T, когда использовал ResultWrapper. Я использовал как:

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>, но затем пытается сделать Either.Right(requestFunc.invoke()) говорит, что ожидает T, R, а я только возвращаю T. Есть идеи, как этого добиться?

РЕДАКТИРОВАТЬ

Я знаю, как это сделать с ResultWrapper, но яХотелось бы узнать, как использовать Either, чтобы я мог использовать fold() и получить оба результата.

То, как я это сделал, использует: data class Success<out T : Any>(val value: T) : ResultWrapper<T>()

1 Ответ

0 голосов
/ 26 октября 2019

Итак, вы хотите использовать 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.

...