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() } }
尽管String
是Any
一个子类型,但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.Collection
, kotlin.List
,…)。
然而, Observable
当然不是一个Kotlin类,所以编译器无法知道Observable<String>
可以在需要Observable<Any>
地方安全地使用。 所以我们必须手动告诉编译器,我们可以只使用Observable<T>
一个子集,而不要把T
作为参数,所以我们会得到好的继承。 这种“子集类型”在Kotlin中被称为类型投影 ,这种技术被称为使用地点方差。
您可以在官方语言文档“ 泛型”一节中阅读有关Kotlin中声明和使用站点差异的更多信息。