2017-08-04 59 views
1

我遇到了以下代码无法在kotlin中编译的问题。Kotlin类型不匹配编译错误:需要成功<T>,找到MyError

// StateModel.kt 
sealed class StateModel 
class Loading : StateModel() 
data class Success<T: Any>(val data: T) : StateModel() 
data class MyError(val message: String) : StateModel() 

// StateModelTransformer.kt 
class StateModelTransformer<T: Any> : FlowableTransformer<T, StateModel> { 

    override fun apply(upstream: Flowable<T>): Publisher<StateModel> { 
    return upstream 
     .map { data -> Success(data) } 
     .onErrorReturn { error -> 
     MyError(error.message) // compile error, Type mismatch, Require Success<T>, Found MyError 
     } 
     .startWith(Loading()) // compile error, none of the following function can be called with the arguments supplied 
    } 

} 

我不知道为什么onErrorReturn说需要Success<T>类型,而是一个StateModel类型。

感谢

回答

3

以下是Flowable相关声明,以供参考。我们忽略onErrorReturn;这与这里的问题无关。

public Flowable<T> { 
    public <R> Flowable<R> map(Function<? super T, ? extends R> mapper); 
    public Flowable<T> startWith(T value); 
} 

这些是Kotlin推断的类型。

val upstream: Flowable<T> 
val mapper: (T) -> Success<T> = { data -> Success(data) } 
val map:  ((T) -> Success<T>) -> Flowable<Success<T>> 
            = upstream::map 
val mapped: Flowable<Success<T>> = map(mapper) 
val loading: Loading    = Loading() 
val startWith: 
    (Success<T>) -> Flowable<Success<T>> 
            = mapped::startWith 

startWith(loading) // type mismatch 

更具体的Success<T>类型已经较早推断,而且科特林不会回溯找到更一般的StateModel类型。要强制要做到这一点,你可以手动陈述类型,例如

// be explicit about the general type of the mapper 
upstream.map { data -> Success(data) as StateModel }.startWith(Loading()) 

// be explicit about the generic type R = StateModel 
upstream.map<StateModel> { data -> Success(data) }.startWith(Loading()) 

顺便说一句,你目前在StateModel失去<T>。我建议改变基类以包含类型参数。

sealed class StateModel<out T: Any> 
object Loading : StateModel<Nothing>() 
data class Success<T: Any>(val data: T) : StateModel<T>() 
data class MyError(val message: String) : StateModel<Nothing>() 

这将让你写,例如,

val <T: Any> StateModel<T>.data: T? 
    get() = when (this) { 
     is Success -> data 
     else -> null 
    } 
+0

感谢您的详细解释。 – akabc

相关问题