Справочник функций

Ваш аккаунт

Войти через: 
Забыли пароль?
Регистрация
Информацию о новых материалах можно получать и без регистрации:

Почтовая рассылка

Подписчиков: -1
Последний выпуск: 19.06.2015

Использование enum

87
11 апреля 2009 года
Kogrom
2.7K / / 02.02.2008
Изучаю перечисления в Java. Столкнулся с такой проблемой: можно определить такое:

enum Numbers {ZERO, ONE, TWO, THREE}

и через ordinal() получать соответствующие номера. Однако, у меня не получилось объявить что-то типа:

enum Numbers {ZERO, TWO = 2, THREE}

чтобы пропустить ненужные константы.

Возможен ли подобный синтаксис в Java?

Читал, что можно определить в enum свои переменные и методы. Таким образом вроде бы можно создать перечисление с двумя конструкторами, которое бы возвращало то, что надо. Но придется для каждого подобного enum описывать те же переменные и функции - получается ненужное дублирование кода. Наследовать же от enum у меня не получилось.
355
11 апреля 2009 года
<SCORP>
786 / / 21.10.2006
Код:
enum Number {
  private int number;
  private Number(int number) {
    this.number = number;
  }
  public int getNumber() { return number; }

  // ну, это уже по надобности.
  // хотя скорее всего, в этой задаче именно вот это и надо
  public static getByNumber(int number) {
    switch (number) {
    case 1:
      return ONE;
    case 2:
      return TWO;
    }
   
    ONE(1),
    TWO(2)
  }
}
87
11 апреля 2009 года
Kogrom
2.7K / / 02.02.2008
Ок. Уточню вопрос. Я понимаю, что так можно сделать. Я тоже подобный вариант сделал:

Код:
enum Numbers {

    ZERO, THREE(3), FOUR, EIGHT(8), NINE;
    private final int val;
    private static int nextVal = 0;

    private int IncNextVal(int setVal) {
        if (setVal != 0) {
            nextVal = setVal;
        }
        return nextVal++;
    }

    Numbers() {
        val = IncNextVal(0);
    }

    Numbers(int n) {
        val = n;
        IncNextVal(val);
    }

    int GetVal() {
        return val;
    }
}

Только в моем случае можно произвольное число констант добавить.

Проблема в том, что мне приходиться в каждом enum все эти функции и переменные повторять. А хотелось бы что-то вроде

 
Код:
enum Numbers extends CppEnum{
    ZERO, THREE(3), FOUR, EIGHT(8), NINE
}


То есть создать родительский класс с "правильным" перечислением и от него наследовать. Но что-то не получается.

Добавлено позже: В моем варианте надо бы еще исключение добавить (или как-то сообщить компилятору), если пользователь захочет произвести инициализацию числом, меньшем, чем в предыдущей константе. Но пока я сделал по простому.
87
12 апреля 2009 года
Kogrom
2.7K / / 02.02.2008
Я еще немного подумал и понял, что этот enum имеет очень мало общего с тем enum, который есть в C++. В Java это скорее массив (или контейнер) именованных объектов. То есть, если искать аналогию в C++, то тут ближе stl::map, чем enum.

Однако, массив именованных объектов тоже полезная штука. Но каждый раз определять её интерфейс как-то лениво, да и неправильно. Наверно, тут надо копать в сторону Enum с большой буквы, чтобы можно было наследовать...
276
15 апреля 2009 года
Rebbit
1.1K / / 01.08.2005
Цитата: Kogrom
Однако, массив именованных объектов тоже полезная штука. Но каждый раз определять её интерфейс как-то лениво, да и неправильно. Наверно, тут надо копать в сторону Enum с большой буквы, чтобы можно было наследовать...


Тут не просто именованые объекты, а еще и поддержка сравнения через == и сериализацыи. А именно для того чтоб сравнивать через == гарантируется существование одного екземпляра для каждого мембера перечисления. Отсюда и спецыфика десериализацыи. Если сериализировать, а потом десериализировать елемент перечисления мы всеровно получим один и тот же екземпляр.

Наследовать перечисления дело не совсем безопасное. И похоже в данном случае невозможное изза конструкцыи Class Enum<E extends Enum<E>> (хотя я полностю не уверен что невозможное)
Одной из причин использования енумов вместо констант есть дополнительный контроль типов. Если будет наследование - появится возможность приведения до базового типа. Тут же и неоднозначность реализацыи equals().

Можно поинтересоватся зачем понадобился енум с явным указанием ordinal ?
В любом случае если нечто подобное нужно, его можно реализировать самостоятельно в обход стандартного енума. Правда без потерь думаю не обойдестя. Наверно от switch придется отказатся.

5
15 апреля 2009 года
hardcase
4.5K / / 09.08.2005
Цитата: Rebbit
Можно поинтересоватся зачем понадобился енум с явным указанием ordinal ?


Бывает нужен, например, для битовых масок в C#:

 
Код:
[Flags]
public enum MyEnum : int {
    Option1 = 1,
    Option2 = 2,
    Option3 = 4
}
Но, в дотнет иная система типов.


Хотя то, что сделал Kogrom, больше напоминает реализацию вариантного типа (из Nemerle).
87
15 апреля 2009 года
Kogrom
2.7K / / 02.02.2008
Цитата: Rebbit

Можно поинтересоватся зачем понадобился енум с явным указанием ordinal ?


Например, в C++ у меня была программа, которая использовала 2 енума из разных классов, причем не было одинковых констант (грубо говоря с одинаковым ordinal), так как во втором enum порядок начинался с определенного номера. Понятно, что это можно легко обойти.

Пример: есть инкапсулированный в классе первый набор констант, идущих подряд, и открытый второй набор состоящий из двух констант, которые равны первому и последнему элементу из первого набора.

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

При этом программист может не задумываться о значении констант.


Извините за сложные формулировки.

Далее. Иногда в C++ удобно применить enum как маску, фильтр определенных значений. В этом случае тоже хорошо бы иметь возможность пропускать значения в enum.

47K
24 июля 2009 года
maximus86
3 / / 19.02.2009
А константы можно привязывать к enum вот так:
enum E {
A(1), B(5), C(18);
int i;
E(int i) { this.i = i; }
}

PS. Помните, что в Java enum - это класс. У него могут быть свои методы, поля и даже контструкторы. Возможно использовать даже полиморфизм.
Для глубокого понимания еще раз рекомендую вышеуказанную статью.
502
31 июля 2009 года
Jail
550 / / 30.01.2007
Цитата: maximus86
А константы можно привязывать к enum вот так:
enum E {
A(1), B(5), C(18);
int i;
E(int i) { this.i = i; }
}

PS. Помните, что в Java enum - это класс. У него могут быть свои методы, поля и даже контструкторы. Возможно использовать даже полиморфизм.
Для глубокого понимания еще раз рекомендую вышеуказанную статью.


О оно че =))
Для глубокого понимания, стоит запомнить, что enum'ми не стоит злоупотреблять. зачастую они просто используются для задания опций и для дальнейшего перенаправления enum'a в метод, т.е. используется в сигнатуре метода. Удобно и пракично.
Ну например, вот так вот (используется nio.2 из jdk7):

Код:
// copy each source file/directory to target
        for (i=0; i<source.length; i++) {
            Path dest = (isDir) ? target.resolve(source.getName()) : target;

            if (recursive) {
                // follow links when copying files
                EnumSet<FileVisitOption> opts = EnumSet.of(FileVisitOption.FOLLOW_LINKS);
                TreeCopier tc = new TreeCopier(source, dest, prompt, preserve);
                Files.walkFileTree(source, opts, Integer.MAX_VALUE, tc);
            } else {
                // not recursive so source must not be a directory
                try {
                    if (Attributes.readBasicFileAttributes(source).isDirectory()) {
                        System.err.format("%s: is a directory%n", source);
                        continue;
                    }
                } catch (IOException x) { }
                copyFile(source, dest, prompt, preserve);
            }
        }
Реклама на сайте | Обмен ссылками | Ссылки | Экспорт (RSS) | Контакты
Добавить статью | Добавить исходник | Добавить хостинг-провайдера | Добавить сайт в каталог