Изменить тип свойства на подкласс в дочернем классе - PullRequest
1 голос
/ 17 октября 2019

У меня есть класс AbstractListFragment со свойством viewModel типа AbstractListViewModel. Как я могу изменить тип этого свойства на подкласс AbstractListViewModel в дочернем классе AbstractListFragment

Я пробовал это:

abstract class AbstractListViewModel()

abstract class AbstractListFragment() {
   abstract var viewModel : AbstractListViewModel
}

class ChildListViewModel() : AbstractListViewModel()

class ChildListFragment() {
   override lateinit var viewModel : ChildListViewModel
}

Однако я получаю:

Свойство Var имеет значение ChildListViewModel, которое не является типом переопределения

Ответы [ 2 ]

0 голосов
/ 18 октября 2019

В вашем коде две проблемы

Во-первых, ChildListFragment необходимо расширить AbstractListFragment , чтобы переопределить его поле

class ChildListFragment() : AbstractListFragment() 

Второе,Вы не можете переопределить var с помощью подкласса типа свойства, потому что он нарушает Принцип подстановки Лискова . Если какой-то метод ожидает AbstractListFragment и вы передаете туда ChildListFragment , метод может назначить некоторого другого дочернего элемента AbstractListViewModel viewModel и ChildListFragment сломается, потому что для него требуется ровно ChildListFragment

class AnotherChild() : AbstractListFragment()

fun someMethod(AbstractListFragment fragment) {
    fragment.viewModel = AnotherChild() // <= here ChildListFragment would expect ChildListViewModel but would get AnotherChild
}

fun main() {
    someMethod(ChildListFragment())
}

Если вы хотите вернуть ChildListViewModel из ChildListFragment , вам следует изменить viewModel в значении val

abstract class AbstractListFragment() {
    abstract val viewModel : AbstractListViewModel
}

class ChildListFragment() : AbstractListFragment() {
    override val viewModel : ChildListViewModel
}

Вы можете использовать поле запекания lateinit, как показано ниже:

class ChildListFragment() : AbstractListFragment() {
    private lateinit var _viewModel: ChildListViewModel

    override val viewModel : ChildListViewModel by lazy {
        _viewModel
    }
}

Или вы можете использовать другие методы, такие как MVP (см. Библиотека Moxy *, например, 1040 *).

0 голосов
/ 17 октября 2019

Вы можете параметризовать свой класс AbstractListFragment с типом модели представления:

abstract class AbstractListViewModel()

abstract class AbstractListFragment<T : AbstractListViewModel>() {
    abstract var viewModel: T
}

class ChildListViewModel() : AbstractListViewModel()

class ChildListFragment() : AbstractListFragment<ChildListViewModel>() {
    override lateinit var viewModel: ChildListViewModel
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...