Если вы всегда используете перечисления вместо констант в Java
В java < 1.5 константы будут реализованы следующим образом:
public class MyClass {
public static int VERTICAL = 0;
public static int HORIZONTAL = 1;
private int orientation;
public MyClass(int orientation) {
this.orientation = orientation;
}
...
и вы будете использовать его следующим образом:
MyClass myClass = new MyClass(MyClass.VERTICAL);
Теперь, в 1.5, очевидно, вы должны использовать перечисления:
public class MyClass {
public static enum Orientation {
VERTICAL, HORIZONTAL;
}
private Orientation orientation;
public MyClass(Orientation orientation) {
this.orientation = orientation;
}
...
и теперь вы будете использовать его следующим образом:
MyClass myClass = new MyClass(MyClass.Orientation.VERTICAL);
Что я считаю немного уродливым. Теперь я мог бы легко добавить пару статических переменных:
public class MyClass {
public static Orientation VERTICAL = Orientation.VERTICAL;
public static Orientation HORIZONTAL = Orientation.HORIZONTAL;
public static enum Orientation {
VERTICAL, HORIZONTAL;
}
private Orientation orientation;
public MyClass(Orientation orientation) {
this.orientation = orientation;
}
...
И теперь я могу сделать это снова:
MyClass myClass = new MyClass(MyClass.VERTICAL);
Со всем безопасным типом перечислений.
Это хороший стиль, плохой стиль или нет. Можете ли вы придумать лучшее решение?
Обновление
Вилкс был первым, кто подчеркнул, что я чувствую, что мне не хватает - что перечисление должно быть первоклассным гражданином. В java это означает, что он получает свой собственный файл в пакете - у нас нет пространств имен. Я думал, что это будет немного тяжеловесом, но, на самом деле, это действительно правильно.
Ответ Yuval в порядке, но на самом деле это не особо подчеркивало не вложенное перечисление. Кроме того, что касается 1.4 - в JDK есть много мест, которые используют целые числа, и я действительно искал способ разработки такого кода.
Ответы
Ответ 1
Не знаю о Java, но в .NET хорошая практика заключается в том, чтобы переводить перечисления параллельно классу, который их использует, даже если он используется одним классом. То есть, вы должны написать:
namespace Whatever
{
enum MyEnum
{
}
class MyClass
{
}
}
Таким образом, вы можете использовать:
MyClass c = new MyClass(MyEnum.MyValue);
Ответ 2
Вы слишком много усложнили. Пусть все вместе.
Опубликовать Java 1.5 вы должны использовать класс Java Enum:
public enum Color
{
BLACK, WHITE;
}
Предварительно Java 1.5 вы должны использовать шаблон Enum, безопасный для типов:
public class Color
{
public static Color WHITE = new Color("white");
public static Color BLACK = new Color("black");
private String color;
private Color(String s)
{
color = s;
}
}
В обоих случаях вы вызываете его так:
drawBackground(Color.WHITE);
В частности, в отношении вашего вопроса. Это вопрос стиля кода, но я думаю, что предпочтительным способом является сохранение перечислений в их отдельных классах. Особенно, когда они начинают использовать свои собственные методы, такие как getName()
, getId()
и т.д. Думайте об этом как о той же дилемме, что и обычный класс против анонимного класса, как только класс начинает забиваться, пришло время переместить его в свой собственный файл.
Ответ 3
Знаете ли вы, что можете импортировать Ориентацию и сказать
MyClass myClass = new MyClass(Orientation.VERTICAL);
?
Ответ 4
Это зависит от того, сколько значений может принять перечисление. В вашем примере, только с двумя, я бы просто использовал логическое значение. Если перечисление будет использоваться только кодом, который вы пишете, и вам не придется взаимодействовать с большим количеством другого кода, возможно, вам не нужна безопасность типов. Но если он в "общедоступном" методе, я бы определенно пошел на перечисления и поместил перечисление в свой собственный файл.
Ответ 5
В MyClass также есть два статических метода:
MyClass.Vertical() : MyClass
MyClass.Horizontal() : MyClass
Те возвращают новый экземпляр с соответствующим набором перечислений.
Ответ 6
Я согласен, что вы были творческими, но я думаю, что это не практическое решение, и я думаю, что вы просто переместили "уродство" на другую часть кода. Что произойдет, если в дополнение к VERTICAL и HORIZONTAL вы также получите DIAGONAL, AA, BB, CC и т.д.? Вам придется дублировать, набирая каждую статическую константу? Ваш вкус, который MyClass.Orientation.VERTICAL уродлив, может быть личным?
Ответ 7
Существует важный класс случаев, когда вы должны использовать константы вместо enum
s. Это когда вы хотите выполнить арифметику с использованием констант или сравнить их с числовыми значениями. Тогда вам действительно нужна вещь int
, long
или double
.
И наоборот, если бы не было смысла делать арифметические или численные сравнения с использованием вещи, эта вещь должна быть скорее объектом, чем примитивным числом, поэтому более подходящим будет enum
.