Как комбинировать классовые случаи?

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

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

case class Order(id: Long, order: String, date: Date)

Для проверки формы Play я бы предоставил отдельный класс case:

case Class inputableOrder(order: String)

Могу ли я затем создать класс Order, который будет получать переменные из inputableOrder и добавлять их в класс Order?

case class Order(id: Long, date: Date) // <- some way to add the variable from inputableOrder?

Я просто пытаюсь предотвратить повторение, но мне все еще нужны два разных класса case (один для проверки формы, а другой для работы с базой данных).

Есть ли способ изменить существующий класс класса, удалить переменную или изменить тип переменной?


person John    schedule 14.07.2013    source источник
comment
Я думаю, что вы используете слово тип, когда имеете в виду переменную, поле, свойство, параметр или аргумент. В первом примере Order, Long, String и Date — это типы, а id, order и date — это имена переменных.   -  person Tim    schedule 14.07.2013
comment
@Tim В основном меня беспокоит тип параметра, так как я не могу получить сообщение о флажке в виде списка (даже если я делаю для каждого и вставляю Int), потому что тип переменной класса case - Int и Play Проверка формы будет принимать сообщение только как Int, если только я не использую другой класс case с другим типом, отличным от того, который используется Slick.   -  person John    schedule 14.07.2013


Ответы (1)


Я думаю, что у вас есть несколько вариантов здесь:

  1. Сделайте InputableOrder частью Order:

    case class InputableOrder(order: String) // ...
    case class Order(input: InputableOrder, id: Long, date: Date) // ..
    

    Это, пожалуй, самое идиоматичное решение. Но это может быть негибким, если вы позже поймете, что InputableOrder нужно что-то, чего не должно быть в Order.

  2. Сделать Order подклассом InputableOrder. В этом случае происходит некоторое повторение кода при передаче аргументов в суперкласс, а суперкласс не может быть классом case, поэтому вам нужно объявить его как обычный класс и создать экстрактор самостоятельно:

    class InputableOrder(val order: String) // ...
    object InputableOrder {
      def unapply(o: InputableOrder): Option[String] = Some(o.order);
      // if you have more than one constructor arguments, return
      // a tuple like Option[(String,String)] etc.
    }
    
    case class Order(override val order: String, id: Long, date: Date)
      extends InputableOrder(order) // ...
    

    Опять же, могут возникнуть те же проблемы, что и с предыдущим пунктом.

  3. Сделайте классы отдельными и создайте вспомогательные методы для преобразования между ними. Выбор зависит от вашего дизайна, но я считаю это решение наиболее гибким:

    case class InputableOrder(order: String);
    case class Order(order: String, id: Long, date: java.util.Date) {
      // An additional constructor to use when converting from Inputable:
      def this(other: InputableOrder, id: Long, date: java.util.Date) =
        this(other.order, id, date);
      // Update this instance with `other`:
      def this(that: Order, other: InputableOrder) =
        this(other, that.id, that.date);
    
      def toInput = InputableOrder(order);
    }
    

    Таким образом, вы можете создать Order из InputableOrder, просто заполнив недостающие поля, и наоборот. Вам нужно написать эти вспомогательные методы/конструкторы один раз, но затем их легко использовать.

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

    implicit def toInput(other: InputableOrder): Order = other.toInput;
    

    чтобы сделать вещи еще проще.

person Petr    schedule 14.07.2013