Métodos generics de Kotlin y inheritance

En mi código, me gustaría crear un método en una class abstracta, que devuelve algo de Observable. Entonces la implementación de esta class abstracta devolvería Observable de cierto tipo (especificado). Lamentablemente, Android Studio devolverá un error "No coinciden los types" en el método de implementación ():

  • Esperado: Observable
  • Encontrado: Observable <{package} .DrawerItemEntity>

My MockDrawerList.getList() devuelve Observable<DrawerItemEntity>

por favor concéntrese en execute() y buildUseCaseObservable

Clase abstracta

 public abstract class UseCase(threadExecutor: ThreadExecutor, postExecutionThread: PostExecutionThread) { private val threadExecutor: ThreadExecutor private val postExecutionThread: PostExecutionThread private var subscription: Subscription = Subscriptions.empty() init { this.postExecutionThread = postExecutionThread this.threadExecutor = threadExecutor } protected abstract fun buildUseCaseObservable(): Observable<Any> public fun execute(useCaseSubsriber: Subscriber<Any>) { subscription = buildUseCaseObservable() .subscribeOn(Schedulers.from(threadExecutor)) .observeOn(postExecutionThread.getScheduler()) .subscribe(useCaseSubsriber) } public fun unsubsribe() { if (!subscription.isUnsubscribed()) subscription.unsubscribe() } } 

Implementación

 Inject class GetDrawerListUseCase(threadExecutor: ThreadExecutor, postExecutionThread:PostExecutionThread) : UseCase(threadExecutor, postExecutionThread) { override fun buildUseCaseObservable(): Observable<Any> { return MockDrawerList.getList() } } 

Aunque String es un subtipo de Any , Observable<String> no se considera un subtipo de Observable<Any> en Kotlin. Debe usar la varianza del sitio de uso : cambie el tipo de retorno de buildUseCaseObservable a Observable<out Any> u Observable<*> (este último es equivalente a Observable<out Any?> ) Y el código debería comstackrse.

¿Por qué la inheritance de los types generics no funciona automáticamente en function de sus parameters de tipo? Este es un problema mejor explicado por Joshua Bloch en Java efectivo, artículo 28: Use comodines delimitados para boost la flexibilidad de la API. En pocas palabras, esto puede funcionar solo cuando se garantiza que el tipo no consumirá instancias de sus parameters de tipo, es decir, si una class con un parámetro genérico T no tiene methods que tomen T como parámetro. Una forma de aplicar esto en Kotlin es mediante la varianza del sitio de statement , que es el caso, por ejemplo, de las interfaces de colección ( kotlin.Collection , kotlin.List , …).

Sin embargo, Observable es, por supuesto, una class de Kotlin, por lo que el comstackdor no tiene forma de saber que Observable<String> se puede usar con security donde se espera un Observable<Any> . Entonces, tenemos que decirle manualmente al comstackdor que estamos bien utilizando solo un subset de características de Observable<T> que no tome T como parámetro, de modo que obtendremos la buena inheritance en su lugar. Este "tipo de subset" se denomina proyección de tipo en Kotlin y la técnica se llama varianza del sitio de uso.

Puede leer más sobre la statement y la variación del sitio de uso en Kotlin en la documentation del idioma oficial, sección Generics .

  • RxJava manejador de error pnetworkingeterminado
  • RxJava 2 requiere un tipo de retorno Observable diferente de RxJava 1 (Kotlin)
  • Operador RxJava para el método de conmutación
  • Pausa / Reanudar un timer / retraso en RX
  • Rxjava retrofit parse api error para el usuario
  • Datos de caching de request HTTP en RxJava
  • kotlin grpc.StreamObserver para deletar en rx.PublishSubject
  • Cambiar Observable desde AutoCompleteTextView a EditText
  • RxJava Valor pnetworkingeterminado para throttleFirst
  • RxJava2 cómo separar diferentes implementaciones de emisor observable
  • ¿Cómo se coordina una list de ejecuciones Completables con RxJava?