Kotlin泛型:Kotlin不承认我的类具有正确的继承
这是我的简单例子:
interface IMyView interface IMyViewModel<VIEW : IMyView, in ITEM> { fun attachView(view: VIEW) fun getView(): VIEW? } class myView : IMyView class MyViewModel : IMyViewModel<myView, String> { override fun attachView(view: myView) { TODO("not implemented") } override fun getView(): myView? { TODO("not implemented") } } abstract class MyBaseClass<VIEWMODEL : IMyViewModel<out IMyView, *>> : IMyView { protected lateinit var viewModel: VIEWMODEL fun myInvocation(): Unit { viewModel.attachView(this as IMyView) } } class MyMainClass : MyBaseClass<MyViewModel>()
问题是最后一行,因为MyViewModel不被识别为IMyViewModel。 错误信息如下:
Type argument is not within its bounds. Expected: IMyViewModel<IMyView, *> Found: MyViewModel
在Java中,它的作品。 我必须适应什么才能使它在Kotlin中也可行?
******更新******
如果你使用
abstract class MyBaseClass<VIEWMODEL : IMyViewModel<out IMyView, *>>
(请参阅上面更新的Kotlin代码)
那么我不能调用myInvocation因为那个调用我需要在IMyView中。 所以这是一场灾难。 我所做的一切都会导致其他问题。 在Java中这很容易。
您的代码的问题是,当您创建一个上限VIEWMODEL : IMyViewModel<IMyView, *>
,类型可以满足此绑定只有实现IMyViewModel
与VIEW
类型参数完全替换IMyView
,不允许IMyView
子类型因此MyViewModel
被拒绝)。 换句话说, VIEW
是不变的 。
由于Kotlin允许您在声明站点和使用站点指定类型参数差异,因此可以通过执行以下操作之一来解决此问题:
-
使用声明站点差异使
IMyViewModel
的VIEW
类型参数协变:interface IMyViewModel<out VIEW : IMyView, in ITEM> ^^^
-
在
VIEWMODEL
上限的IMyViewModel
的使用位置添加一个out
IMyViewModel
:abstract class MyBaseClass<VIEWMODEL : IMyViewModel<out IMyView, *>> ^^^
-
将另一个类型参数
T
添加到MyBaseClass
,并在IMyViewModel<T, *>
使用它:abstract class MyBaseClass<T : IMyView, VIEWMODEL : IMyViewModel<T, *>> class MyMainClass: MyBaseClass<myView, MyViewModel>()
我现在解决了这个问题。 我犯了一个概念错误。 这是解决方案:
interface IMyViewModel<VIEW : IMyView, in ITEM> { fun attachView(view: VIEW) fun getView(): VIEW? } class MyViewModel : IMyViewModel<IMyView, String> { override fun attachView(view: IMyView) { TODO("not implemented") //To change body of created functions use File | Settings | File Templates. } override fun getView(): IMyView? { TODO("not implemented") //To change body of created functions use File | Settings | File Templates. } } abstract class MyBaseClass<VIEWMODEL : IMyViewModel<IMyView, *>> : IMyView { protected lateinit var viewModel: VIEWMODEL fun myInvocation(): Unit { viewModel.attachView(this) } } class MyMainClass : MyBaseClass<MyViewModel>()