Должно ли вы определить нулевое/неизвестное значение для перечислений Java?
Когда вы определяете перечисление для того, что может быть "undefined" в ваших интерфейсах, вы должны
- определите для него отдельное значение перечисления или
- просто используйте enumValue = null для этих ситуаций?
Например,
serviceX.setPrice(Цена priceEnum)
enum Price {
CHEAP, EXPENSIVE, VERRRY_EXPENSIVE, UNKNOWN
}
и priceEnum.UNKNOWN при необходимости
или
enum Price {
CHEAP, EXPENSIVE, VERRRY_EXPENSIVE
}
и priceEnum = null при необходимости?
Немного спорить об этом. Некоторые моменты, которые приходят на ум:
- с помощью Price.UNKNOWN сохраняет код "if (price == null)". Вы можете обрабатывать Price x все значения в одном коммутационном футляре
- В зависимости от технологии просмотра может быть проще локализовать Price.UNKNOWN
- используя метод Price.UNKNOWN причины "магического номера" в коде, IMO. Здесь у нас есть Price.UNKNOWN, в другом месте, возможно, Color.UNDEFINED, Height.NULLVALUE и т.д.
- using priceValue = null более равномерен с тем, как обрабатываются другие типы данных в Java. Мы имеем Integer я = null, DomainObject x = null, String s = null для неизвестных значений, не так ли?
- Price.UNKNOWN заставляет вас решить, разрешено ли null-значение для всех случаев использования. У нас может быть метод Price getPrice(), который может возвращать Price.UNKNOWN и setPrice (Цена p), которым запрещено принимать Price.UNKNOWN. Поскольку Price.UNKNOWN всегда включен в значения перечисления, эти интерфейсы выглядят немного нечистыми. Я знаю, что priceValue = null имеет ту же проблему (вы не можете определить в интерфейсе, принимается ли null или нет), но он чувствует себя немного чище и немного менее вводит в заблуждение (?)
Ответы
Ответ 1
Это на самом деле пример применения Null Object pattern. ИМХО всегда лучше иметь фиктивный объект, а не нуль. Например, вы можете добавлять фиктивные методы к нулевому объекту, а не разбрасывать свой код с нулевыми проверками повсюду. Очень удобно.
Также имя enum
дает вам дополнительную семантику: неизвестна ли цена, undefined, не заслуживает доверия, еще не известна? И что это означает, если цена равна нулю?
ОБНОВЛЕНИЕ: Как указывает Аарон Дигулла, для шаблона Null Object требуется память. Но в большинстве случаев это не так. В традиционной реализации вы обычно используете singleton для объекта Null, который используется везде, так как нет необходимости в отдельных экземплярах. Он становится еще лучше с перечислениями, потому что вы получаете семантику singleton бесплатно.
Другим моментом является то, что ссылка null
и ссылка на некоторый объект занимают тот же объем памяти (скажем, 4 байта на 32-битной машине). Это ссылка на объект, который занимает некоторую дополнительную память. Но если это синглтон, здесь накладных расходов практически нет.
Ответ 2
Я бы сказал, идите с Price.UNKNOWN
, если это допустимое значение для цены.
Я согласен с недостатками обращения с нулевыми ссылками, которые вы упоминаете, и я думаю, что они мотивируют это решение.
Новые языки, возьмите Scala, например (и некоторые более старые, Haskell), отделяйте от нулевых ссылок все вместе и вместо этого используйте опцию/возможно монады... по уважительным причинам.
Ответ 3
Это зависит от того, как вы собираетесь использовать это перечисление. Если вы используете его в операторах switch/case, это не имеет значения.
Если вы создадите метод в перечисление, вы должны действительно определить UNKNOWN.
Например, вы можете определить абстрактный метод
public abstract Icon icon();
в свой список, а затем реализовать этот метод для каждого члена Прайса. Вероятно, вам нужно будет отобразить знак вопроса по неизвестной цене. В этом случае просто реализуйте метод icon()
, который создает соответствующий значок.
Ответ 4
Существует Enum-Switch-Null-Trap.
Таким образом, похоже, что как с любым свойством, являющимся объектом,
если он не существует, то он null
.
Ответ 5
Цвет или высота будут использоваться в логике программы. Они не могут обрабатывать цвет undefined.
Цена - это userdata и может быть неизвестна.
Цвет может быть userdata else, но для использования в качестве цвета в коде они должны быть определены.
Итак, цена может быть UNKNOWN (вместо null), Color not (null может указывать на ошибку).