Enum и Generic Constant специфический метод - PullRequest
0 голосов
/ 22 октября 2010

У меня есть перечисление вроде:

    enum TEST {
        TEST1, TEST 2;

        public abstract <T> String stringify (T input);
    }

Мне нужно добавить определенный метод, например, stringify.

Этот метод будет принимать различные типы входных данных (для каждого перечисления),Могу ли я сделать это?Затмение не позволяет мне сделать это .. что-то вроде:

enum TEST {
    TEST1(
       public <Float> String stringify (Float input){
          return String.valueOf(input);
        }
    )
}

Ответы [ 5 ]

3 голосов
/ 22 октября 2010

Вы не можете сделать это с enum s, но вы можете смоделировать это поведение с помощью универсального класса:

public abstract class TEST<T> {
    public static final TEST<Float> TEST1 = new TEST<Float>() {
        public String stringify (Float input){   
            return String.valueOf(input);   
        }
    };

    public abstract <T> String stringify(T input);
}
2 голосов
/ 17 марта 2011

вы можете сделать это. но не ясно, в чем выгода:

enum TEST {
    TEST1 {
        public <Float>String stringify(Float input) {
            System.out.println("TEST1");
            return String.valueOf(input);
        }
    },
    TEST2 {
        public <Integer>String stringify(Integer input) {
            System.out.println("TEST2");
            return String.valueOf(input);
        }
    },
    TEST3 {};
    public <T>String stringify(T input) {
        System.out.println("super");
        return "";
    }
    public <Integer>String stringify2(Object input) {
        System.out.println("non generic");
        return String.valueOf(input);
    }
}
public class Main{
    public static void main(String[] args) {
        for(TEST test:TEST.values()) {
            System.out.println(test.stringify(new Float(1.23)));
            System.out.println(test.stringify(new Integer(42)));
            System.out.println(test.stringify(new Double(4.56)));
        }
        for(TEST test:TEST.values()) {
            System.out.println(test.stringify2(new Float(1.23)));
            System.out.println(test.stringify2(new Integer(42)));
            System.out.println(test.stringify2(new Double(4.56)));
        }
    }
}
0 голосов
/ 02 ноября 2012

Вы не можете использовать дженерики с перечислениями, потому что сами константы перечисления уже являются конкретными (одноэлементными) экземплярами.На уровне экземпляра дженерики уже должны быть конкретными.
Итак, я бы настоятельно рекомендовал использовать одну из альтернатив, приведенных в других ответах.

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

public enum TestEnum {
    Test1(Float.class),
    Test2(Integer.class),
    Test3(String.class);

    private final Class<?> iInputType;

    private TestEnum(final Class<?> pInputType) {
        iInputType = pInputType;
    }

    public Class<?> getInputType() {
        return iInputType;
    }

    public String stringify(final Object pInput) {
        return String.valueOf(iInputType.cast(pInput));
    }
}

Тестовый код:

System.out.println(TestEnum.Test1.stringify(1.23f));
System.out.println(TestEnum.Test2.stringify(42));
System.out.println(TestEnum.Test3.stringify("foo"));
// but:
// System.out.println(TestEnum.Test1.stringify("foo")); // -> ClassCastException!

for (TestEnum test : TestEnum.values()) {
    for (Object input : new Object[]{1.23f, 42, "foo"}) {
        if (test.getInputType().isAssignableFrom(input.getClass())) {
            System.out.println(test.stringify(input));
        }
    }
}
0 голосов
/ 22 октября 2010

Нет, вы не можете заставить каждую константу перечисления реализовывать абстрактный метод, но требовать ввод другого типа, чем другие константы перечисления.Если бы вы могли, что бы произошло, если бы вам дали экземпляр вашего TEST перечисления (вы не знаете, что это за константа) и попытались вызвать stringify для него?Какой тип вы бы передали?

Редактировать: Учитывая то, что вы сказали об этих перечислениях, используемых для декодирования строк в объекты, мне кажется, у вас есть несколько вариантов:

  • Вы можете получить представление String каждого декодированного объекта, просто вызвав для него toString().
  • Вы можете добавить набор перегруженных статических методов в сам класс enum, называемый stringify(Float) и stringify(Double), и т. Д. Тогда вы можете просто вызвать TEST.stringify(value), и если бы для типа значения был метод stringify, он бы работал нормально.

Я думаю, что естьа также другие варианты.

0 голосов
/ 22 октября 2010

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

http://download.oracle.com/javase/tutorial/java/javaOO/enum.html

Посмотрите на пример планеты.

Также обратите внимание, что само перечисление может иметь статические методы .... (как класс)

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