#scala #default-value #case-class
#scala #значение по умолчанию #case-класс
Вопрос:
В большинстве случаев значения по умолчанию очень подходят, но в некоторых случаях я хочу проверить, были ли они установлены вручную.
Пример
//most fields with default value
case class Person(
name: Option[String] = None,
name2: Option[String] = None,
bithYear: Option[Int] = None
)
object OtherPersonToPersonConverter {
def convert(other: OtherPerson): Person = {
Person(
name = other.name,
name2 = other.name2,
bithYear = other.bithYear
)
}
Затем я добавил другое поле со значением по умолчанию
case class Person(
name: Option[String] = None,
name2: Option[String] = None,
bithYear: Option[Int] = None,
city: Option[String] = None
)
Я должен исправить конвертер, но я не знаю об этом из-за использования значения по умолчанию. Есть ли какой-либо способ создать объект без использования значений по умолчанию (и выдать ошибку времени компиляции)?
Комментарии:
1. трудно понять, что и зачем вам нужно, поскольку вы отклонили ответ Джатина ниже…
Ответ №1:
Как насчет просто:
case class Person(
name: Option[String] = None,
name2: Option[String] = None,
bithYear: Option[Int] = None,
city: Option[String]
)
Комментарии:
1. Этот код генерирует ошибку времени компиляции при каждом создании Person, но нужен только для некоторых из них (с особым способом построения объекта? может быть)
2. поэтому используйте ошибку компиляции, чтобы найти код, который нуждается в обновлении, а затем добавьте обратно значение по умолчанию… что в этом плохого?
3. В этом случае программиста не заставляют это делать. Он просто отредактировал класс Person и забыл об этом. Я ищу способ заставить его редактировать зависимый класс, даже если он использует значения по умолчанию
4. @paul_di Вот почему вышеупомянутое будет работать, поскольку компилятор не позволит ему успешно скомпилироваться, если он забыл добавить. Ему нужно будет обязательно установить значение.
5. @paul_di, ни у кого другого (например, у компилятора) нет надежного способа сообщить программисту, где они должны заполнить поля, в их старом коде, потому что, когда они хотели заполнить все значения, они использовали
Person(...)
, а когда они хотели использовать значения по умолчанию, они также использовалиPerson(...)
. Только программист может знать, что есть что. Все, что вы действительно можете сделать сейчас, чтобы исправить старый код, — это выполнить поиск по нему, и этот ответ предоставляет способ начать этот поиск, вызвав ошибки компиляции.
Ответ №2:
Вы можете создать столько функций конструктора, сколько захотите. Хорошее место для их размещения — в сопутствующем объекте:
object Person {
def create(name: Option[String], name2: Option[String], ...): Person = Person(
name = name,
name2 = name2,
...
)
}
Функция конструктора Person(...)
эквивалентна Person.apply(...)
, то есть вызывает apply()
метод сопутствующего объекта, поэтому вы просто создаете другой, определяя Person.create()
(или называйте как хотите). Создавая несколько функций конструктора, одну со значениями по умолчанию, а другую без, вы можете контролировать, используются ли значения по умолчанию при создании вашего Person
экземпляра, выбирая, какой метод вы вызываете.
Если это работает лучше для вас, вы могли бы сделать так, чтобы create()
были аргументы по умолчанию, а не определять аргументы по умолчанию для apply()
(то есть в case class
определении).
Комментарии:
1. Это близко к решению. В отдельной функции вы все еще вызываете default apply, который поддерживает значения по умолчанию. Но для любого другого программиста странно редактировать класс и не исправлять сопутствующий объект.
2. Что ж, вам нужно принять некоторые решения в вашем коде. Если вы используете
case class
, то значение по умолчаниюapply()
будет вызываться для всех созданных объектов (даже если вы используетеnew
). Итак, если вы хотите иметь возможность создавать объект без возможности использования значений по умолчанию, вы должны либо (1) использовать метод default apply без значений по умолчанию, а другой метод — со значениями по умолчанию, либо (2) не использоватьcase class
синтаксис, чтобы онnew Person(...)
не вызывалPerson.apply()
, а затем вручную реализовать желаемую функциональность, котораяcase class
дала бы вам.