Kotlin泛型方法和继承

在我的代码中,我想在抽象类中创建一个方法,该方法返回一些Observable。 然后这个抽象类的实现将返回某些(指定)类型的Observable。 不幸的是,Android Studio会在实现方法()中返回一个错误“类型不匹配”:

  • 预计:可观察
  • 找到:Observable <{package} .DrawerItemEntity>

我的MockDrawerList.getList()返回Observable<DrawerItemEntity>

请关注execute()buildUseCaseObservable

抽象类

 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() } } 

履行

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

尽管StringAny一个子类型,但Observable<String> Observable<Any>在Kotlin中被视为Observable<Any>的子类型。 你应该使用use-site变量 :将buildUseCaseObservable的返回类型改为Observable<out Any>Observable<*> (后者相当于Observable<out Any?> ),代码应该被编译。

为什么通用类型的继承不能基于类型参数自动工作? 这是Joshua Bloch在Effective Java中最好解释的问题,项目28:使用有界通配符来提高API的灵活性。 简而言之,只有当类型被保证不消耗类型参数的实例时,也就是说,如果一个具有泛型参数T的类没有以T作为参数的方法,它才能工作。 在Kotlin中可以强制执行的一种方法是声明站点差异 ,例如对于集合接口( kotlin.Collectionkotlin.List ,…)。

然而, Observable当然不是一个Kotlin类,所以编译器无法知道Observable<String>可以在需要Observable<Any>地方安全地使用。 所以我们必须手动告诉编译器,我们可以只使用Observable<T>一个子集,而不要把T作为参数,所以我们会得到好的继承。 这种“子集类型”在Kotlin中被称为类型投影 ,这种技术被称为使用地点方差。

您可以在官方语言文档“ 泛型”一节中阅读有关Kotlin中声明和使用站点差异的更多信息。