Following code snippet doesn't compile (Kotlin 1.7.0) because in PFrag when calling it's parent (Frag) constructor, V is not recognized as a subtype of ViewModel<PRepo>.
However I think it should because V type is PViewModel<M, R> with PViewModel being a child of ViewModel and R being a child of PRepo.
Is it possible to slighlty modify this code to make it compile (maybe using out keyword) ?
Or is it impossible due to some issues I have not yet seen ?
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>()
CodePudding user response:
Let's break this down:
For
Frag<PRepo, V>to work, it must be the case thatV : ViewModel<PRepo>, according to the constraints inFrag.We know that
V: PViewModel<M, R>, and alsoPViewModel<M, R>: ViewModel<R>from their respective declarationsTherefore,
V: ViewModel<R>Even though
R: PRepo,V: ViewModel<R>does not implyV: ViewModel<PRepo>. For this to be true,Rneeds to be marked asout:abstract class ViewModel<out R: Repo>This prevents you from writing any method/property in
ViewModelwhereRis in an input position. You can also do:abstract class Frag<R: Repo, V: ViewModel<out R>>which prevents you from using any members from
VwhereRis in an input position.Alternatively, change the base class of
PFragtoFrag<R, V>so thatV : ViewModel<R>is required, rather thanV : ViewModel<PRepo>:abstract class PFrag<M: PModel, R: PRepo, V: PViewModel<M, R>>: Frag<R, V>()
Which of those ways is the most suitable depends on your situation. I cannot tell without more information about what these types represent, though I think changing the base class is most likely what you intended.
