以下代码片段无法编译(Kotlin 1.7.0),因为在PFrag
调用它的父 ( Frag
) 构造函数时,V
它不被识别为ViewModel<PRepo>
.
但是我认为它应该是因为V
类型是PViewModel<M, R>
作为PViewModel
孩子的孩子ViewModel
和R
孩子的孩子PRepo
。
是否可以稍微修改此代码以使其编译(可能使用out
关键字)?还是因为一些我还没有看到的问题而不可能?
interface Model
abstract class Repo
abstract class ViewModel<R: Repo>
abstract class Frag<R: Repo, V: ViewModel<R>>
interface PModel: Model
abstract class PRepo: Repo()
abstract class PViewModel<M: PModel, R: PRepo>: ViewModel<R>()
abstract class PFrag<M: PModel, R: PRepo, V: PViewModel<M, R>>: Frag<PRepo, V>()
让我们分解一下:
为了Frag<PRepo, V>
工作,它必须是这样的V : ViewModel<PRepo>
,根据 中的约束Frag
。
我们知道V: PViewModel<M, R>
,也PViewModel<M, R>: ViewModel<R>
从他们各自的声明中知道
所以,V: ViewModel<R>
即使R: PRepo
,V: ViewModel<R>
并不意味着V: ViewModel<PRepo>
。为此,R
需要标记为out
:
abstract class ViewModel<out R: Repo>
这可以防止您在输入位置中ViewModel
写入任何方法/属性。R
你也可以这样做:
abstract class Frag<R: Repo, V: ViewModel<out R>>
这会阻止您使用处于输入位置的V
任何成员。R
或者,将基类更改PFrag
为Frag<R, V>
所需V : ViewModel<R>
的,而不是V : ViewModel<PRepo>
:
abstract class PFrag<M: PModel, R: PRepo, V: PViewModel<M, R>>: Frag<R, V>()
哪种方式最适合取决于您的情况。如果没有关于这些类型代表什么的更多信息,我无法判断,尽管我认为更改基类很可能是您想要的。
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句