Должны ли мы всегда отдавать предпочтение полиморфизму перед перечислениями? - PullRequest
22 голосов
/ 19 декабря 2008

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

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

Ответы [ 6 ]

13 голосов
/ 19 декабря 2008

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

13 голосов
/ 19 декабря 2008

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

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

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

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

11 голосов
/ 19 декабря 2008
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 {}

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

7 голосов
/ 19 декабря 2008

Стесняюсь назвать что-нибудь злом . Это вопрос о том, «Как тяжело вы хотите это сконструировать».

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

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

3 голосов
/ 19 декабря 2008

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

Обычно.

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

1 голос
/ 19 декабря 2008

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

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

...