如果提供RxJava Observable,Kotlin密封类子类需要被转换为基类
我试图避免在我的应用程序中写入Kotlin的RxJava链终端状态,所以我发现将ResultSet封装类的Observable<T>
转换为Observable<Result<T>>
是正确的。
sealed class Result<T> data class Success<T>(val data: T) : Result<T>() data class Failure<T>(val throwable: Throwable) : Result<T>()
假设我有这个网络请求可观察。
fun getOrganization(): Observable<Result<Boolean>> { return api.getOrganization("google") .map { Success(true) } .onErrorReturn { Failure(RuntimeException("throwable")) } }
所以我最终想做的就是这样处理结果。
fun main(args: Array<String>) { getOrganization().subscribe({ when (it) { is Success -> print("success = ${it.data}") is Failure -> print("failure = ${it.throwable}") } }) }
一切都应该很好,但我在IDE中有这个错误。
这不是简单的使用子类而不是基类吗?
我发现,如果我明确地投入Success(true)
的Result<Boolean>
一切正常,但显示此警告。
为什么它甚至发生,我在这里做错了什么?
UPD。 看起来这里的主要问题是rxjava的onErrorReturn运算符。 如果我完全删除它,那么它甚至没有关键字像答案建议。
如果我从map和onErrorReturn返回Success
,那么out
关键字有助于摆脱错误。
但是,如果我从onErrorReturn返回Failure
仍然有错误。 编译器必须知道“ Failure
Result
与“ Success
键入的Boolean
相同。 我应该怎么做才能避免它或满足它的要求?
也许你误解了kotlin中的一般变化。 它工作正常,因为Success<Boolean>
是Result<Boolean>
的子类型。 所以“ 不需要投 ”警告报告和下面的代码工作正常:
val ok:Success<Boolean> = Success(true); val result:Result<Boolean> = ok;
但是 ,由于类型参数不同,因此不能将Success<Boolean>
指定给Result<Any>
,所以为什么编译器会报告“ 类型不匹配 ”错误,例如:
val ok:Success<Boolean> = Success(true); val result1:Result<Any> = ok;// error val result2:Result<out Any> = ok;// ok
要修复错误和警告,您可以尝试下面的代码:
fun getOrganization(): Observable<out Result<Boolean>> { return api.getOrganization("google") .map<Result<Boolean>> { Success(true) } .onErrorReturn { Failure(RuntimeException("throwable")) } }
有关更多详细信息,可以看到java通用子类型和kotlin类型的投影 。
Observable<Success<Boolean>>
不是Observable<Result<Boolean>>
List<String>
的子类型,就像List<String>
不是List<Object>
的子类型一样。 请参阅泛型文档。
为了解决这个问题,可以返回一个Observable<out Result<Boolean>>
,或者直接在你的map
函数中添加一个类型:
.map<Result<Boolean>> { Success(true) }