Kotlin Generics: Котлин не признает мой класс с правильным наследованием

это мой упрощенный пример:

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 это работает. Что мне нужно адаптировать, чтобы сделать его работоспособным в Котлине?

****** Обновить ******

Если вы используете

 abstract class MyBaseClass<VIEWMODEL : IMyViewModel<out IMyView, *>> 

(см. обновленный код Котлина выше)

то я не могу вызвать myInvocation, потому что для этого вызова мне нужно «в IMyView». Поэтому это катастрофа. Все, что я делаю, приводит к другим проблемам. Это было проще в Java.

Проблема с вашим кодом заключается в том, что когда вы создаете верхнюю границу VIEWMODEL : IMyViewModel<IMyView, *> , тип может удовлетворять этой привязке только в том случае, если он реализует IMyViewModel с параметром типа VIEW замененным точно IMyView , подтип IMyView не разрешен ( и поэтому MyViewModel отклоняется). Другими словами, VIEW инвариантен .

Поскольку Kotlin позволяет вам указать дисперсию параметра типа как на сайте объявления, так и на сайте использования, вы можете исправить это, выполнив одно из следующих действий:

  • Сделать параметр типа IMyViewModel ковариации IMyViewModel с IMyViewModel дисперсии объявления-сайта:

     interface IMyViewModel<out VIEW : IMyView, in ITEM> ^^^ 
  • Добавьте out -projection на сайт-сайт IMyViewModel в верхней грани VIEWMODEL :

     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>() 
Intereting Posts