Kotlin Advanced Typing: абстрактные классы, интерфейсы для упрощения преобразования классов комнат в другие классы - PullRequest
0 голосов
/ 01 ноября 2019

У меня есть несколько сущностей комнаты (WEntity) и соответствующие модели, не относящиеся к комнате (WModel).

Сущности комнаты объединены для создания иерархии (WHierarchy) (grandparent ->list (parent) -> list (children) -> ...).

Мне нужно иметь возможность преобразовывать сущности в соответствующие им модели и иерархии в соответствующие им модели. (Например, FooModel имеет FooEntity данных плюс список BarModels (сопоставленный с BarEntity).

В настоящее время я представляю эту иерархию, например, FooHierarchy(val parent: FooEntity, val children: List<BarEntity>).

Вот мои начальные интерфейсы, описывающие то, что они должны сделать как можно лучше:

interface WModel

interface WEntity<T: WModel> {
    fun toModel(): T
}

abstract class WHierarchy<Parent: WEntity<ParentModel>, Child: WEntity<ChildModel>, ParentModel: WModel, ChildModel: WModel> {
    abstract val parent: Parent
    abstract val children: List<Child>
    fun toModel(): ParentModel {
        return when(this) {
            is WOHierarchy -> parent.toModel().copy(lgs=children.map { it.toModel() })
            else -> throw IllegalStateException("bork bork bork")
        }
    }
}

Вот примеры объектов:

data class WOEntity(val id: Int): WEntity<WO> {
    override fun toModel(): WO {
        return WO(id=id, lgs=emptyList())
    }
}

data class LGEntity(val id: Int): WEntity<LG> {
    override fun toModel(): LG {
        return LG(id=id)
    }
}

и ихсоответствующие модели:

data class WO(val id: Int, val lgs: List<LG>): WModel
data class LG(val id: Int): WModel

И иерархия:

data class WOHierarchy(override val parent: WOEntity, override val children: List<LGEntity>): WHierarchy<WOEntity, LGEntity, WO, LG>()

Моя проблема, с которой я сталкиваюсь, - мой абстрактный класс WHierarchy. Текущая оценка реализации

parent.toModel().copy(lgs=children.map { it.toModel() })

и говорит "Несоответствие типов: Обязательный: ParentModel. Найдено: WO."

Я в замешательстве: WO реализует ParentModel! Как сделатьЯ это исправлю? Разве компилятор не сможет сказать, что WO реализует ParentModel, и, таким образом, я возвращаю ParentModel так, как должен?

Это все попытка абстрагировать HierarchytoModel() (и, в конечном итоге, fromModel() объекта-компаньона), что довольно наглядно, потому что у меня на самом деле четыре или пять Hierarchy-ImplemeОпределение классов точно таким же образом, одни и те же ключевые слова, просто другой возвращаемый класс (отсюда и интерфейс WModel, который в противном случае ничего не делает).

1 Ответ

0 голосов
/ 01 ноября 2019

после приведения равно WOHierarchy -> parent.toModel() компилятору известно, что функция parent.toModel () возвращает WO, а тип Parent - WOEntity. и вы говорите ему, что возвращаемый тип внутри функции модели абстрактного класса - Parent вам нужно изменить в абстрактном классе

fun toModel(): WModel 

-

abstract class WHierarchy<Parent : WEntity<ParentModel>, Child : WEntity<ChildModel>, ParentModel : WModel, ChildModel : WModel> {
    abstract val parent: Parent
    abstract val children: List<Child>
    fun toModel(): WModel {
        return when (this) {
            is WOHierarchy -> parent.toModel().copy(lgs = children.map { it.toModel() })
            else -> throw IllegalStateException("bork bork bork")
        }
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...