【问题标题】:Enum and Generic constant specific method枚举和通用常量特定方法
【发布时间】:2012-11-03 03:33:34
【问题描述】:

我有一个像这样的枚举:

    enum TEST {
        TEST1, TEST 2;

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

我需要添加一个常量特定的方法,比如 stringify。

此方法将采用不同类型的输入(对于每个枚举)。我可以这样做吗? Eclipse 不允许我这样做..类似于:

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

【问题讨论】:

  • 1.如何调用此方法?_______ 2.您的代码是否真的将函数作为构造函数参数传递,或者您是否打错了大括号?

标签: java enums


【解决方案1】:

enums 无法做到这一点,但可以使用泛型类模拟这种行为:

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】:

    你可以做到。但不清楚有什么好处:

    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)));
            }
        }
    }
    

    【讨论】:

      【解决方案3】:

      将每个 Enum 值视为一个类。所以是的,枚举可以有方法,就像一个类一样——尽管它们都有相同的方法。

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

      看看 Planet 的例子。

      还要注意枚举本身可以有静态方法....(就像一个类)

      【讨论】:

      • 我知道......但我想要在每个枚举类型上使用不同类型的常量特定方法。在这种情况下,如果使用 Float 调用 TEST1,则可能会使用 Double 调用 TEST2。
      • @gats,我认为你能做的最好的事情,从另一个答案中查看你的评论,就是在枚举本身上有一个静态方法,并根据枚举值做一些不同的事情。
      • @hvgotcodes:这不是正确的建议。人们应该将整个枚举声明视为一个类。构成枚举的每个常量都成为枚举类的一个实例。因此,特定于常量的方法有点违反直觉。能够定义特定于常量的行为很好,但我们通常不认为类实例与同一类的其他实例具有不同的行为。
      【解决方案4】:

      不,您不能让每个枚举常量都实现一个抽象方法,但需要与其他枚举常量不同的输入类型。如果可以的话,如果给你一个 TEST 枚举的实例(你不知道它是什么常量)并试图调用 stringify 会发生什么?你会通过什么类型的?

      编辑:鉴于您所说的这些枚举用于将字符串解码为对象,在我看来您有几个选择:

      • 您可以通过调用toString() 来获得每个解码对象的String 表示。
      • 您可以在枚举类本身上添加一组重载静态方法,称为stringify(Float)stringify(Double) 等。然后您可以只调用TEST.stringify(value) 并且如果值的类型有stringify 方法,它可以正常工作。

      我想还有其他选择。

      【讨论】:

      • 所以解决方案是传入 Object 作为参数,在实现中,让每个枚举类型将输入转换为必要的类型?
      • @gats:嗯……不。那真的不是一个好主意。你能编辑你的问题来解释你想通过这样做来完成什么吗?我们或许可以提出更好的替代方案。
      • 已有代码使用枚举将字符串值编码为特定类型...现在我需要添加解码功能...
      • 并不总是 toString 方法。并且使用重载我将不得不编写很多方法。
      • @gats:如果您也为每个枚举常量执行一个方法,您将不得不编写很多方法,您的意思是什么?
      【解决方案5】:

      您不能将泛型与枚举一起使用,因为枚举常量本身已经是具体(单例)实例。在实例级别,泛型必须已经是具体的。
      因此,我强烈建议您使用其他答案中给出的替代方案之一。

      如果您必须在枚举中执行此操作,您可以考虑以下内容,它至少为您提供了一种运行时类型检查的方法,包括 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));
              }
          }
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多