如果提供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运算符。 如果我完全删除它,那么它甚至没有关键字像答案建议。

没有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类型的投影 。

java通用子类型

Observable<Success<Boolean>>不是Observable<Result<Boolean>> List<String>的子类型,就像List<String>不是List<Object>的子类型一样。 请参阅泛型文档。

为了解决这个问题,可以返回一个Observable<out Result<Boolean>> ,或者直接在你的map函数中添加一个类型:

 .map<Result<Boolean>> { Success(true) }