Соответствует ли соответствие шаблону Scala принципу Open/Closed?

Если я добавлю новый класс case, значит ли это, что мне нужно выполнить поиск по всему шаблону соответствия шаблону и узнать, где должен обрабатываться новый класс? Недавно я изучал язык, и когда я читал о некоторых аргументах для сопоставления шаблонов и против них, я был смущен тем, где его следует использовать. См. Следующее:

Pro: Odersky1 и Odersky2

Con: Beust

Комментарии тоже очень хороши в каждом случае. Точно так же шаблон, соответствующий чему-то, что нужно возбуждать или что-то, что я должен избегать использовать? Фактически, я полагаю, что ответ "зависит от того, когда вы его используете", но каковы некоторые положительные варианты использования для него и какие-то негативные?

Ответы

Ответ 1

Джефф, я думаю, у вас есть правильная интуиция: это зависит.

Иерархии объектно-ориентированных классов с диспетчером виртуальных методов хороши, если у вас есть относительно фиксированный набор методов, которые необходимо реализовать, но многие потенциальные подклассы, которые могут наследоваться от корня иерархии и реализовать эти методы. В такой установке относительно легко добавлять новые подклассы (просто реализовать все методы), но относительно сложно добавлять новые методы (вам нужно изменить все подклассы, чтобы убедиться, что они правильно реализуют новый метод).

Типы данных с функциональностью, основанной на сопоставлении с образцом, хороши, если у вас относительно фиксированный набор классов, относящихся к типу данных, но многие потенциальные функции, которые работают с этим типом данных. В такой установке относительно легко добавить новые функции для типа данных (просто совпадение шаблонов на всех его классах), но относительно сложно добавить новые классы, которые являются частью типа данных (вам нужно изменить все функции, которые соответствуют на тип данных, чтобы убедиться, что они правильно поддерживают новый класс).

Канонический пример для подхода OO - это графическое программирование. Элементы GUI должны поддерживать очень небольшую функциональность (при этом на экране минимальный минимум), но все новые элементы GUI добавляются все время (кнопки, таблицы, диаграммы, слайдеры и т.д.). Канонический пример для подхода совпадения шаблонов - это компилятор. Языки программирования обычно имеют относительно фиксированный синтаксис, поэтому элементы дерева синтаксиса будут меняться редко (если вообще когда-либо), но новые операции с деревьями синтаксиса постоянно добавляются (более быстрая оптимизация, более тщательный анализ типов и т.д.).

К счастью, Scala позволяет объединить оба подхода. Классы классов могут совпадать с шаблоном и поддерживать отправку виртуальных методов. Регулярные классы поддерживают диспетчеризацию виртуальных методов и могут быть сопоставлены с шаблоном, определяя экстрактор в соответствующем сопутствующем объекте. Это зависит от того, подходит ли программисту, когда каждый подход подходит, но я думаю, что оба они полезны.

Ответ 2

Пока я уважаю Седрика, он совершенно не прав по этому вопросу. Scala сопоставление шаблонов может быть полностью инкапсулировано из изменений класса по желанию. Хотя верно, что изменение класса case потребует изменения любых соответствующих экземпляров соответствия шаблонов, это происходит только при наименее использовании таких классов.

Scala сопоставление шаблонов всегда делегирует деконструктору объекта сопутствующего класса. С классом case этот деконструктор автоматически создается (вместе с методом factory в сопутствующем объекте), хотя по-прежнему можно переопределить эту автоматически сгенерированную версию. Во все времена вы можете полностью контролировать процесс сопоставления шаблонов, изолируя любые шаблоны от потенциальных изменений в самом классе. Таким образом, сопоставление образцов - это просто еще один способ доступа к данным класса через безопасный фильтр инкапсуляции, как и любой другой метод.

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

Что касается того, где он должен использоваться, это полностью соответствует вкусу. Если это сделает ваш код более кратким и удобным, используйте его! В противном случае, не надо. Для большинства объектно-ориентированных программ сопоставление шаблонов не требуется. Однако, как только вы начнете интегрировать более функциональные идиомы (Option, List и т.д.), Я думаю, вы обнаружите, что соответствие шаблонов значительно сократит синтаксические издержки, а также улучшит безопасность, предлагаемую системой типов. В общем, в любое время, когда вы хотите извлекать данные, одновременно проверяя некоторые условия (например, извлекая значение из Some), сопоставление шаблонов, вероятно, будет полезно.

Ответ 3

Совпадение шаблонов, безусловно, хорошо, если вы выполняете функциональное программирование. В случае OO есть некоторые случаи, когда это хорошо. В самом примере Седрика это зависит от того, как вы концептуально рассматриваете метод print(). Это поведение каждого объекта Term? Или это нечто вне его? Я бы сказал, что это снаружи, и имеет смысл делать сопоставление образцов. С другой стороны, если у вас есть класс Employee с различными подклассами, это плохой выбор дизайна для сопоставления шаблонов по его атрибуту (например, имя) в базовом классе.

Также сопоставление шаблонов предлагает элегантный способ распаковки членов класса.