【问题标题】:How do I create an interface with methods that take an instance of some enum type?如何使用采用某种枚举类型的实例的方法创建接口?
【发布时间】:2012-05-27 07:45:04
【问题描述】:

我想到了一个接口,它声明了一种将调查中的原始分数转换为特定类别的百分位值的方法,其中类别由多个其他不相关的枚举类型描述。所以我从这个开始:

public interface NormTable<E extends Enum<E>> {
    Integer percentileForRawScore(E e, int score);
}

然后我得到了一个实现类,例如 Foo 调查及其Subscale 枚举:

public class FooSubscaleNormTable implements NormTable<Subscale> {
    public Integer percentileForRawScore(Subscale e, int score) {
        // Implementation
    }
}

最后,一个用于创建适当具体类的工厂类:

public class NormTableFactory {
    public static <E extends Enum<E>> NormTable<E> normTableForSurveyAndType(
        String surveyCode, Class<E> clazz) {
    if ("Foo".equals(surveyCode) && Subscale.class.equals(clazz)) {
        return (NormTable<E>) new FooSubscaleNormTable();
    } else {
            // ...
        }
    }
}

我怀疑那里的演员阵容是错误的,因为 Eclipse 将其标记为未选中,但让我继续。然而,构建服务器上的 Java 1.6 编译器并不满意,并将它们标记为不可转换的类型。

是我在工厂类中的签名有误,还是我的整个架构看起来很可疑?我在上面注意到枚举类型是“否则不相关的”,尽管它们都代表调查中的类别,并且可以想象实现一个接口来统一它们的类型。这会有帮助吗?

【问题讨论】:

标签: java generics interface enums


【解决方案1】:

您不应在声明类型中使用具体的 Enum 类。

使 FooSubscaleNormTable 也通用

public class FooSubscaleNormTable<E extends Enum<E>> implements NormTable<E> {
    public Integer percentileForRawScore(E e, int score) {
       if(e instanceof Subscale) {
           switch((Subscale) e) {
           case X:
           // do something
           break;
           }
       }
       // return 0; 
    }
}

把你的工厂改成

public class NormTableFactory {
    public static <E extends Enum<E>> NormTable<E> normTableForSurveyAndType(
        String surveyCode, Class<E> clazz) {
    if ("Foo".equals(surveyCode) && Subscale.class.equals(clazz)) {
        return (NormTable<E>) new FooSubscaleNormTable<E>();
    } else {
            // whatever else
        }
    }
}

然后当您调用它时,即传入您想要的枚举类型。

NormTable<Subscale> scale = NormTableFactory.normTableForSurveyAndType("surveyCode", Subscale.class);

【讨论】:

  • 谢谢你,我快到了。但是,在使FooSubscaleNormTable 成为泛型时,我似乎失去了引用特定枚举类型的能力。例如,该类采用Subscale 枚举,我需要能够确定它在percentileForRawScore() 中的值,如下所示:if (e == Subscale.Bar) { // ... }。同样,Eclipse 没有对此进行标记,但构建服务器上的 OpenJDK 1.6 编译器并不满意:incomparable types: E and Subscale.Bar
  • 枚举的好处是您可以在 switch 语句中使用它们。试试switch(e) {case Bar: some statement; break; case ... }
  • 我从 Eclipse 得到 Cannot switch on a value of type E...,但 E extends Enum&lt;E&gt; 在类声明中。我有点难过。我可能需要从头开始。
  • 没错,因为在编译时,编译器不知道泛型枚举的类型是什么。如果percentileForRawScore 将采用几种类型的枚举作为参数,您将不得不进行实例检查和强制转换。如果它总是只接受Subscale,你根本不需要泛型,你可以简单地将方法更改为percentileForRawScore(Subscale s, int score) 并删除instancecheck 和cast,并从类中删除泛型类型。
  • 信不信由你,我也不能投:inconvertible types。解决方案是使用e.equals(Subscale.Bar) 而不是e == Subscale.Bar,并返回到if 语句而不是开关。 stackoverflow.com/questions/8087337/…
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-08-31
  • 1970-01-01
相关资源
最近更新 更多