问题描述
我试图在用Kotlin编写的应用程序中避免RxJava链的终端状态,所以我发现将Observable<T>
转换为Observable<Result<T>>
(其中Result
是密封类)是正确的.
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运算符附近.如果我将其完全删除,则即使没有out
关键字(如答案建议)也可以使用它.
如果我同时从map和onErrorReturn返回Success
,则out
关键字有助于消除错误.
但是,如果我从onErrorReturn返回Failure
,仍然会出现错误.编译器必须知道Failure
Result
的键入方式与Success
相同.我应该怎么做才能避免它或满足它的要求?
也许您误解了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类型投影.
I'm trying to avoid terminal states of RxJava chains in my app written in Kotlin, so I found out that it is right thing to transform Observable<T>
to Observable<Result<T>>
where Result
is sealed class.
sealed class Result<T>
data class Success<T>(val data: T) : Result<T>()
data class Failure<T>(val throwable: Throwable) : Result<T>()
And let's say I have this network request observable.
fun getOrganization(): Observable<Result<Boolean>> {
return api.getOrganization("google")
.map { Success(true) }
.onErrorReturn { Failure(RuntimeException("throwable")) }
}
So what I want to do in the end is to handle result like this.
fun main(args: Array<String>) {
getOrganization().subscribe({
when (it) {
is Success -> print("success = ${it.data}")
is Failure -> print("failure = ${it.throwable}")
}
})
}
Everything should work great, but I have this error in IDE.
Isn't it just simple using of subclass instead of base class?
I found out that if I explicitly cast Success(true)
to Result<Boolean>
everything works, but shows this warning.
Why it even happens and what am I doing wrong here?
UPD.It looks like the main issue here is near rxjava's onErrorReturn operator. If I remove it completely, then it works even without out
keyword like answers suggest.
If I return Success
from both map and onErrorReturn then out
keyword helps to get rid of errors.
But if I return Failure
from onErrorReturn there's still error. Compiler has to know that Failure
Result
typed with the same Boolean
as Success
. What should I do to avoid it or to satisfy it's requirements?
maybe you misunderstand the generic variance in kotlin. it works fine since Success<Boolean>
is a subtype of Result<Boolean>
. so the "No need cast" warning reported and the code below works fine:
val ok:Success<Boolean> = Success(true);
val result:Result<Boolean> = ok;
But you can't assign a Success<Boolean>
to a Result<Any>
since their type parameters are different, so this why compiler reports the "Type mismatch" error , for example:
val ok:Success<Boolean> = Success(true);
val result1:Result<Any> = ok;// error
val result2:Result<out Any> = ok;// ok
to fix the error and warnings you can try the code below:
fun getOrganization(): Observable<out Result<Boolean>> {
return api.getOrganization("google")
.map<Result<Boolean>> { Success(true) }
.onErrorReturn { Failure(RuntimeException("throwable")) }
}
for more details, you can see java generic subtypes & kotlin type projections.
这篇关于如果提供为RxJava Observable,则必须将Kotlin密封类子类强制转换为基类的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!