Должны ли мы всегда отдавать предпочтение полиморфизму перед перечислениями?

После просмотра:Чистые переговоры по коду - наследование, полиморфизм и тестирование

Я проверил свой код и заметил, что несколько операторов switch могут быть преобразованы в полиморфизм, но я также заметил, что я использовал только операторы switch с перечислениями. Означает ли это, что перечисления являются «злыми» в ОО-дизайне и должны быть устранены полиморфизмом?

Ответы на вопрос(6)

«Значит ли это, что перечисления являются« злыми »в ОО-дизайне и должны быть устранены полиморфизмом?»

Обычно.

Конструкции switch / enum могут быть любой из ряда полиморфных структур:государственный а такжестратегия два наиболее распространенных из них.

Решение Вопроса

Дело не в том, что перечисления являются злом, это заявления о переключении. Существует долгое обсуждение этого вC ++ FAQ книга, но суть заключается в следующем: за исключением ограниченных областей - например, интерпретация данных, поступающих из регистра на устройстве - большая комбинация переключателей предполагает, что вы используете данные, чтобы различать подтипы. Вместо этого вы должны просто использовать подтипы, получая помощь компилятора в поддержании его правильности, а также означая, что компилятор автоматически добавит новые случаи, когда вы (неизбежно) измените набор случаев.

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

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

Опять же, это исключение. В целом, создание подклассов часто является лучшим решением для языков, которые его хорошо поддерживают.

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

 BobbyShaftoe19 дек. 2008 г., 21:08
В первый раз, когда я увидел сообщение Google «не используйте IF», у меня возникло ощущение, будто это «хорошая идея», а наполовину «это слишком экстремальная пропаганда».

злой, Это вопрос о том, «Как тяжело вы хотите это сконструировать».

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

Мой классический опыт - это компилятор, который я написал для класса несколько лет назад. Мой сосед по комнате был со мной в одном классе, и мы подошли к нему двумя совершенно разными способами. Я выбрал тяжелый подход, полный полимофизма. Он использовал подход с тяжелым Си, используя перечисления и союзы. Его код был ~ 1/2 размером с мой LOC, его код был быстрее для компилятора, и его кодработал, Его код был гибким, потому что онне было overengineered. Это был ценный урок для меня в разработке программного обеспечения.

 Pyrolistical19 дек. 2008 г., 23:17
Да, вы должны создать новый класс, но основная логика кода должна быть такой же, иначе вы делаете что-то не так.
 Paul Nathan19 дек. 2008 г., 23:21
Это дополнительная сложность кодирования, которая делает его нежелательным для небольших переключений.
 BobbyShaftoe19 дек. 2008 г., 21:10
Вот так. Как только вы идете по этому маршруту, вы порождаете много накладных расходов. Внезапно, чтобы получить дополнительный случай, вы должны создать целый класс вместо дополнительного флага и небольшого количества кода.


Кроме того, Enums по-своему называются константами.

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

 shahkalpesh20 дек. 2008 г., 04:49
Вопрос ничего не говорит о Java / C #. Кроме того, я не сказал, что это случай в Java.
 PhiLho19 дек. 2008 г., 22:00
В Java перечисления - это гораздо больше, чем просто набор констант.
class Sunday extends DayOfWeek {}
class Monday extends DayOfWeek {}
class Tuesday extends DayOfWeek {}
class Wednesday extends DayOfWeek {}
class Thursday extends DayOfWeek {}
class Friday extends DayOfWeek {}
class Saturday extends DayOfWeek {}

Перечисления в порядке.

 TheCatWhisperer08 мар. 2017 г., 16:42
Кроме того, когда вам нужно будет локализовать свое приложение, насколько полезным будет ваше перечисление?
 TheCatWhisperer08 мар. 2017 г., 16:35
Что делать, если я хочу заказать их? да, приведенный вами пример является крайним, но есть и другие подходы, помимо перечисленных и перечисляемых: struct DayOfWeek {string Name; int Order; }
 recursive08 мар. 2017 г., 18:18
@TheCatWhisperer: Довольно полезно. например в C #:var day = DayOfWeek.Tuesday; var localized = CultureInfo.CurrentCulture.DateTimeFormat.DayNames[(int)day];

Ваш ответ на вопрос