【问题标题】:Enum<? extends interface>枚举<?扩展接口>
【发布时间】:2012-08-10 21:35:31
【问题描述】:

我正在尝试拥有一个扩展通用接口的枚举集合,例如:

interface Fooable
{
  void someCommonMethod();
}

enum E1 implements Fooable
{
   // some enumuerations and a definition for someCommonMethod()
}

enum E2 implements Fooable
{
   // some different enumerations and a different definition for someCommonMethod()
}

然后通过强制变量是枚举实现接口来在别处使用它。所以有点类似......

bar(Enum<? extends Fooable> fe)
{
  fe.ordinal();
  fe.someCommonMethod();
}

但是,到目前为止,我似乎必须强制转换 fe 才能将其视为实现接口,即,

bar(Enum<? extends Fooable> fe)
{
  fe.ordinal();
  ((Fooable)fe).someCommonMethod();
}

虽然这应该是安全的……但它似乎不是最理想的,我可能会忽略一些东西。当然,如果我尝试仅将参数作为 Fooable 传递,那么我最终将其转换为将其视为枚举,这不仅没有收获,我现在甚至都不安全。请参阅以下内容:

bar(Fooable fe)
{
  // potentially unsafe cast!
  ((Enum<?>)fe).ordinal();
  fe.someCommonMethod();
}

有什么我忽略的或者是什么

Enum<? extends Fooable>

与我能得到的“好”解决方案差不多吗?

我对 Java 还比较陌生,并且仍然在尝试像 C 或 C++ 一样使用它,所以如果我把它当作锤子而不是锯子来对待,或者忽略一些愚蠢简单的东西,请随时指出 :)

【问题讨论】:

    标签: java interface enums type-constraints


    【解决方案1】:

    这意味着 T 扩展了 Enum 并实现了 Fooable:

    <T extends Enum<T> & Fooable>
    

    因此你的方法可以写成:

    <T extends Enum<T> & Fooable> void bar(T fe) {
        fe.ordinal();
        fe.someCommonMethod();
    }
    

    【讨论】:

    • 是的,但我的理解是这仅在声明泛型而不为方法定义参数时使用?
    • 没想到这种方法...已经尝试过使用 T 扩展 Enum 和 Fooable 的接口泛型,但可能不得不四处寻找使封闭类泛型,以便它的所有方法都可以有一个带有两个约束的 T...
    • 不幸的是,这看起来只是在我的代码库中创建了额外的未经检查的强制转换,即 Fooable 接口上的一些方法返回枚举,然后将其分配给 T 类型的变量......并且由于类型擦除这需要未经检查的强制转换。看起来它确实可以在编译时强制执行双重约束……但必须考虑一下。
    • 这将如何改变 Fooable 接口中方法的返回类型?
    【解决方案2】:

    您可以选择将任何您需要的 Enum 方法添加到 Fooable 中,或者创建一个扩展 Fooable 的新接口并添加您需要的 Enum 方法。

    例子:

    interface Fooable {
       void someCommonMethod();
    }
    
    interface FooableEnum extends Fooable {
       int ordinal();
    }
    
    enum E1 implements FooableEnum {
       // Implement someCommonMethod.
       // ordinal() is already implemented by default.
    }
    

    完成此操作后,您可以在方法签名中使用 FooableEnum 作为参数类型,而不必担心任何通用的东西。

    【讨论】:

    • 我曾考虑过这一点,但我对它在 values() 方面的行为有所保留,可能值得重新审视,因为现在我无法挖掘有效的保留。 .
    • 这需要一个不必要的接口。
    • @Mike,我越想越觉得这是正确的道路。我的要求并不是类型 is 是枚举,而是它具有枚举的 行为。我也说服自己 values() 的事情不会成为问题,而且我很傻。
    • @Havard,取决于接口的使用方式。 int ordinal() 可以放置在原始的 Fooable 接口中,但是如果该 Fooable 接口在其他地方被使用,而不需要成为我试图在这里强加的枚举,那么这里完成的第二个接口可能很有用。就我而言,我可能会将两者结合起来;但是单独显示是有利的。
    猜你喜欢
    • 2013-12-07
    • 1970-01-01
    • 2012-07-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多