Как использовать классы case scala при необходимости делегирования

Предположим, что в нашем приложении мы хотим моделировать автомобили. Мы также хотим смоделировать репозиторий автомобилей, где мы храним некоторые зарегистрированные автомобили. Как это должно быть смоделировано в scala?

Вот мой подход: во-первых, я создаю класс case PlainCar. Это просто автомобиль, как он существует в реальном мире, и в нем нет ничего особенного. Затем я создаю CarRepository. Я также создаю RegisteredCar. CarRepository теперь может хранить PlainCar s и верните их как RegisteredCar s. Оба PlainCar и RegisteredCar расширяют признак ---- +: = 8 =: + ----, который предоставляет все методы comon, такие как Car , drive однако особенный - ему принадлежит экземпляр RegisteredCar, но также добавляет метод PlainCar, который возвращает регистрационный номер; все другие методы просто делегируются экземпляру registrationNumber.

Я чувствую, однако, что есть некоторые недостатки этого дизайна. Во-первых, я должен изменить PlainCar, когда добавляю метод /свойство в RegisteredCar, который, я думаю, не нужно делать.

Таким образом, мой вопрос, может ли он быть смоделирован лучше, и если да, то как? Есть ли другие недостатки, которые мне не хватает?

Некоторые советы по соглашениям об именах также будут оценены, потому что PlainCar звучит довольно неудобно для меня.

3 голоса | спросил valenterry 15 Jam1000000amThu, 15 Jan 2015 02:03:22 +030015 2015, 02:03:22

2 ответа


3

Звучит так, как будто регистрация - это состояние, которое имеет смысл только в контексте репозитория. Вы описали два состояния (зарегистрированные в репозитории, не зарегистрированные в репозитории). Мне кажется, что вам нужен контейнер для автомобилей (обертка, если хотите). Подумайте об этом как о коллекции, которая может содержать один автомобиль, так же, как Option [Car] или . Либо [Car, Motorbike] может удерживать только один объект.

Итак, создайте запечатанную базовую признак RepositoryItem (или запечатанный абстрактный класс) и создайте экземпляры класса case (которые расширяют RepositoryItem) для каждого состояния. Зарегистрированный вариант будет иметь регистрационный номер. Создайте хранилище контейнер RepositoryItems . Он не должен быть частью одного и того же набора классов case.

Преимущества такого подхода включают

  • Вы можете сделать его общим ( RepositoryItem [A] или RepositoryItem [+ A] , а не RepositoryItem [Car] ). Это означает, что он может стать хранилищем других вещей (или может легко расширяться, чтобы держать мотоциклы, а также автомобили).
  • Полное разделение проблем между реализацией репозитория и реализацией автомобиля. Можно изменить (или добавить новые функции), не влияя на другие.
  • Вы можете создавать новые подклассы автомобиля так часто, как вам нравится. Даже если вы создаете Репозиторий [Car] с самого начала, вместо того, чтобы сделать его общим, он сможет нести подклассы автомобилей без изменений.

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

EDIT:

Чтобы объяснить точку, которая могла создать путаницу, судя по вашему комментарию ...

Опция и Либо имеют функцию map (как и Список и любая другая монада). Функция карты позволяет вам передать функцию, которая может манипулировать содержащимся объектом. Вы возвращаете преобразованный объект, все еще завернутый в Option.

scala> val o = Some(3)
o: Some[Int] = Some(3)

scala> o map (_ * 5)
res2: Option[Int] = Some(15)

Нет зависимостей между Опции и Int , но поскольку Option реализует карту , вы можете управлять Int , не удаляя его из опции .

ответил itsbruce 15 Jam1000000amThu, 15 Jan 2015 02:30:02 +030015 2015, 02:30:02
2

Я чувствую, что у меня что-то не хватает, но я просто сделаю ваш CarRepository a Map[RegistrationNumber, PlainCar] или что-то подобное. Обычно с неизменяемыми объектами гораздо проще создавать такую ​​ассоциацию вне исходного объекта.

Мой второй выбор был бы RegisteredCar extends PlainCar, но я думаю, что это создает ненужную связь и копии. Обе эти опции позволят вам просто переименовать PlainCar в Car

ответил Karl Bielefeldt 15 Jam1000000amThu, 15 Jan 2015 04:36:28 +030015 2015, 04:36:28

Похожие вопросы

Популярные теги

security × 330linux × 316macos × 2827 × 268performance × 244command-line × 241sql-server × 235joomla-3.x × 222java × 189c++ × 186windows × 180cisco × 168bash × 158c# × 142gmail × 139arduino-uno × 139javascript × 134ssh × 133seo × 132mysql × 132