Java Generics: Перечисления и Интерфейсы - PullRequest
2 голосов
/ 15 ноября 2011

Я читал некоторые темы по этому поводу, но все еще не могу понять, как я могу сделать то, что я хочу сделать:

У меня есть несколько перечислений, которые расширяют определенный интерфейс (HasCode), которая объявляет одну функцию, code(), которая возвращает код int этого перечисления.Все расширяющие перечисления имеют частные int переменные и параметры для своих конструкторов (и т. Д.).

Я хотел бы иметь функцию, которая будет принимать класс перечисления в качестве параметра и возвращать хеш-таблицу имен значений перечисления и значений int этих значений перечисления.

Здесьпример моих перечислений:

public enum InvoiceStatuses implements HasCode<InvoiceStatuses> {
    NONE(0), REQUESTED(10), RECEIVED(20), APPROVED(30), PAID(40), ERROR(-100);
    private int code;
    private InvoiceStatuses(int a) {
        code = a;
    }
    public int code() {
        return code;
    }
    public static InvoiceStatuses invoiceStatusByCode(int aCode) {
        switch (aCode) {
        case 0:
            return NONE;
        case 10:
            return REQUESTED;
        case 20:
            return RECEIVED;
        case 30:
            return APPROVED;
        case 40:
            return PAID;
        }
        return ERROR;
    }
    public int compare(InvoiceStatuses anotherLevel) {
        if (code > anotherLevel.code()) {
            return 1;
        } else if (code < anotherLevel.code()) {
            return -1;
        }
        return 0;
    }
    @Override
    public InvoiceStatuses[] enumValues() {
        return InvoiceStatuses.values();
    }
}

HasCode:

public interface HasCode <T extends Enum<?>>{
    public int code();
    public T[] enumValues();
}

А вот класс с этой магической функцией (которая перебирает значения перечисления)

import java.util.Hashtable;
import java.util.LinkedList;
public class SelectFromEnum&lt;T extends Enum<?>> {
    public SelectFromEnum() {}
    public Hashtable<String, String> createSelect(HasCode<T> anEnum) throws Exception{
        if (! (anEnum instanceof Enum)) {
            throw new Exception ("I only accept enums...");
        }
        T[] values = anEnum.enumValues();
        for (T value : values) {
            System.out.println(value.name() + " __ " + ((HasCode)value).code());
        }
        return null;
    }
}

Что мне не нравится в этом:

1) Я должен передать конкретный член перечисления в качестве параметра функции createSelect, и я хотел быпередать (enum) .class;

2) Я бы хотел, чтобы параметр createSelect указывал, что это Enum , расширяющий данный интерфейс , но я не могувполне понять, как это сделать.

Обновление:

В соответствии с комментарием Инго Кегеля я изменил SelectFromEnum следующим образом (см. ниже), и теперьvalue.name() не компилируется ...

import java.util.Hashtable;
import java.util.LinkedList;

public class SelectFromEnum<C extends HasCode> {
    public SelectFromEnum() {
    }
    public Hashtable&lt;String, String> createSelect(Class<C> anEnum) throws Exception {
        if (!anEnum.isEnum()) { 
            throw new Exception("I only accept enums...");
        }
        C[] values = anEnum.getEnumConstants();
        for (C value : values) {
            System.out.println(value.name() + " __ " + value.code());
        }
        return null;
    }
}

Я могу добавить name() к интерфейсу HasCode, но есть ли способВыясните компилятору, что value является членом перечисления?

Ответы [ 2 ]

8 голосов
/ 15 ноября 2011

Вам не нужно использовать экземпляр перечисления.Вы можете передать класс и использовать Class#isEnum и Class#getEnumConstants().

Редактировать

Вы можете привести к объектам, возвращенным Class#getEnumConstants() в Enumкод должен выглядеть так:

public LinkedList createSelectFrom(Class anEnum) throws Exception {
    if (!anEnum.isEnum()) {
        throw new Exception("I only accept enums...");
    }
    Object[] values = anEnum.getEnumConstants();
    for (Object value : values) {
        System.out.println(((Enum)value).name() + " __ " + ((HasCode) value).code());
    }
}
1 голос
/ 15 ноября 2011

Не уверен, почему вы используете параметр типа для HasCode, просто реализуйте интерфейс для перечислений, которые вы хотите использовать.Я подозреваю, что вы пытались использовать это как способ ограничения реализации перечислениями, но это не должно быть необходимым.Вам не важно, что реализует интерфейс.

Попробуйте по-другому

createSelect(EnumSet.allOf(InvoiceStatus.class));

public Hashtable createSelect(EnumSet<? extends HasCode> enums) {
    for (HasCode c : enums) {
        c.code();
    }
}

Вы гарантированно, что перечисления будут Set из Enum значений, если это имеет значениетебе.Также гораздо проще понять, и вам не нужен экземпляр enum напрямую.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...