Как построить класс данных kotlin из класса blueprint

В моем веб-приложении Spring Boot есть HTML-форма, которая заполняет объект Blueprint:

data class Blueprint(

    // relevant part, validation omitted
    var items: List<Long> = emptyList() // List of ids

    // ...
)

Позже я намерен использовать этот Blueprint для создания Product, который будет классом данных аналогичной структуры:

data class Product(

    val items: List<Item>
    /* Here 'items' is a list of Item objects which are fetched from DB by */
    /* their ids. Item is data class too. */

)

Я бы хотел, чтобы Product использовал объект Blueprint в качестве аргумента конструктора.

Я попытался использовать вторичный конструктор, но он требует, чтобы я сразу вызвал первичный конструктор, прежде чем у меня будет возможность обработать план и, возможно, отфильтровать некоторые идентификаторы элементов.

Конечно, есть обходные пути, такие как фабричная функция, но кажется разумным ожидать, что я могу просто передать проект конструктору.

Есть ли способ сделать это?

0
0
61
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

В основном у вас есть три варианта:

  1. Адаптер: Blueprint.asProduct()
  2. Заводской метод: Product.fromBlueprint(blueprint)
  3. Или просто: Product (blueprint.items.filter {/ * что-то здесь * /}

Это очень сильно зависит от количества элементов между Product и Blueprint.

Если у вас много классов Product, то имеет смысл иметь фабричный метод.

Если вы обычно создаете Product из Blueprint, вам будет удобнее использовать адаптер.

Если вы не можете разобраться, подойдет и третий вариант.

Похоже, фабричный узор - это действительно правильный выбор. Спасибо.

CBlew 14.09.2018 15:29

Создайте вспомогательную функцию внутри сопутствующего объекта, который предоставляет аргументы для основного конструктора. Затем вызовите этот помощник во вторичном конструкторе:

data class Product(val items: List<Item>) {
    constructor(blueprint: Blueprint)
            : this(makeItems(blueprint))

    private companion object {
        fun makeItems(blueprint: Blueprint): List<Item> {
            return blueprint.items
               .filter { ... }
               .map { Item(...) }
        }
    }
}

Если код преобразования короткий, вы, конечно, можете сделать его встроенным:

constructor(blueprint: Blueprint)
        : this(blueprint.items.filter { ... }.map { Item(...) })

Однако, поскольку вы имеете дело с data class, было бы проще предоставить фабричный fromBlueprint(), чтобы люди сразу увидели, что переданный аргумент не является свойством. В качестве альтернативы вызовите конструктор с именованными аргументами, например Product(blueprint = ...).

Другие вопросы по теме