Лучший способ проверить и расширить параметры конструктора в Scala 2.10

Я хочу иметь класс, который имеет ряд полей, таких как String, Boolean и т. д., и когда класс построен, я хочу иметь имя поля, связанное с каждым полем, и проверять поле (используя регулярное выражение для строк). В идеале я хотел бы просто указать в конструкторе, что параметр должен соответствовать определенным критериям.

Некоторый пример кода того, как:

case class Data(val name: String ..., val fileName: String ...) {
  name.verify
  // Access fieldName associated with the name parameter.
  println(name.fieldName) // "Name"
  println(fileName.fieldName) // "File Name"
}

val x = Data("testName", "testFile")
// Treat name as if it was just a string field in Data
x.name // Is of type string, does not expose fieldName, etc

Есть ли элегантный способ добиться этого?

РЕДАКТИРОВАТЬ: я не думаю, что смог четко понять, что мне нужно. У меня есть класс с рядом строковых параметров. Каждый из этих параметров должен быть проверен определенным образом, и я также хочу, чтобы строка fieldName была связана с каждым параметром. Однако я хочу по-прежнему иметь возможность обрабатывать параметр, как если бы это была обычная строка (см. пример).

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


person Stephan    schedule 13.02.2013    source источник
comment
Была ли это опечатка, когда вы написали, что не выставляет имя поля?   -  person Randall Schulz    schedule 14.02.2013
comment
Я обновил пример кода, чтобы сделать его более понятным. Я хочу прикрепить параметр fieldName к каждому параметру конструктора, но я не хочу, чтобы это отображалось снаружи.   -  person Stephan    schedule 14.02.2013
comment
Хорошо, но... откуда взялось это fieldName? Вы всегда можете добавить private val в тело case class, если этого достаточно.   -  person Randall Schulz    schedule 14.02.2013
comment
Вот что я хочу знать. Я хочу иметь возможность обходить логику параметров как для проверки параметра, так и для хранения информации о нем. Мой вопрос в том, есть ли в Scala идиоматический способ сделать это.   -  person Stephan    schedule 18.02.2013
comment
Извините, но я не понимаю, что вы пытаетесь сделать.   -  person Randall Schulz    schedule 18.02.2013


Ответы (1)


Размещение логики (например, проверки параметров) в конструкторах сомнительно. Генерация исключений из конструкторов — это вдвойне.

Обычно этот тип порождающего шаблона лучше всего обслуживается одним или несколькими фабричными методами или каким-либо построителем.

Для базовой фабрики просто определите компаньона с нужными фабричными методами. Если вам нужна такая же сокращенная нотация построения (new-свободная), вы можете перегрузить предопределенный apply (хотя вы не можете заменить тот, чья подпись точно соответствует конструктору case class).

Если вы хотите избавить свой клиентский код от беспорядка обработки исключений, когда проверка не удалась, вы можете вместо этого вернуть Option[Data] или Either[ErrorIndication, Data]. Или вы можете пойти с Validation ScalaZ, который я собираюсь произвольно объявить выходящим за рамки этого ответа (потому что я недостаточно знаком с ним...)

Однако у вас не может быть экземпляров, которые различаются по свойствам, которые они представляют. Даже подклассы не могут вычитаться из общедоступного API. Если вам нужно это сделать, вам понадобится более сложная конструкция, такая как trait для общих частей и отдельные case classes для вариантов и/или расширений.

person Randall Schulz    schedule 14.02.2013
comment
Вы имеете в виду, что нельзя генерировать исключения в конструкторах в исключительных ситуациях? Как насчет require утверждений в конструкторе? - person ziggystar; 14.02.2013
comment
В наши дни я стараюсь избегать исключений (ограничивая их как можно ближе к тому месту, где их может сгенерировать другой код), и я нахожу исключения в конструкторах особенно беспорядочными. И да, это включает require и assert. Я отсылаю вас к заголовку stackoverflow.com/questions/9169691/ - person Randall Schulz; 14.02.2013
comment
Я говорил о ситуации, когда происходит что-то непредвиденное из-за ошибки или чего-то еще. Обычно вы хотите, чтобы ваша программа рухнула, потому что вы все равно не знаете, что делать. Если ожидается исключительная ситуация (например, искаженный пользовательский ввод), то - да - не используйте исключения, но в противном случае? - person ziggystar; 14.02.2013
comment
Конечно. В общем, вы не можете предотвратить это, с одной стороны. Но преднамеренного броска (явно или с помощью assert / require) я избегаю. YMMV (как мы часто говорили...). - person Randall Schulz; 14.02.2013
comment
Привет Рэндалл, я согласен с вами об исключениях в принципе. К сожалению, остальная часть кода написана с использованием исключений и состоит из смеси Scala и Java. Я рад, что код проверки существует вне конструктора в методе применения фабрики. Однако мне нужно иметь доступ к fieldName, которое было присвоено параметру внутри фактического класса. Я отредактирую вопрос, чтобы попытаться сделать его более ясным. - person Stephan; 18.02.2013
comment
Я согласен с @RandallSchulz в том, что нужно избегать использования исключений. Я попадаю в ту же область; проверка параметров класса case. Я только что опубликовал кое-что об этом на дочернем сайте StackOverflow, CodeReview. Если у вас есть время просмотреть его, я был бы признателен за любые ваши отзывы; т. е. помочь уменьшить шаблон, улучшить методы подхода к проблемному пространству и т. д.: -tuple-for-the-parame" title="уменьшение стандартного шаблона при проверке параметров и использование кортежа для параметра">codereview.stackexchange.com/questions/60645/ - person chaotic3quilibrium; 21.08.2014