如何通过枚举管理泛型?

sp0*_*00m 7 java generics enums

我有一个参数化的界面:

public interface MyInterface<T> {
    void run(T e);
}
Run Code Online (Sandbox Code Playgroud)

和实现接口的类:

public class MyClass1 implements MyInterface<SomeOtherClass1> {
    public void run(SomeOtherClass1 e) {
        // do some stuff with e
    }
}

public class MyClass2 implements MyInterface<SomeOtherClass2> {
    public void run(SomeOtherClass2 e) {
        // do some stuff with e
    }
}
Run Code Online (Sandbox Code Playgroud)

不同的MyClass*X*的数量是已知且详尽的,并且每个MyClass*X*只有一个实例,所以我想使用枚举:

public enum MyEnum {
    MY_CLASS_1,
    MY_CLASS_2;
}
Run Code Online (Sandbox Code Playgroud)

为了能够使用MyEnum.MY_CLASS_1.run(someOtherClass1);例如(我会将MyInterface的每个实例放在同一个地方).甚至可能(如果是的话,如何)?因为我现在很困惑......


我还尝试了什么:

public enum MyEnum {

    MY_CLASS_1(new MyClass1()),
    MY_CLASS_2(new MyClass2());

    private MyInterface<?> instance;

    private MyEnum(MyInterface<?> instance) {
        this.instance = instance;
    }

    public void run(/* WhichType? */ e) {
        instance.run(e);
    }

}
Run Code Online (Sandbox Code Playgroud)

在上面的方法中,当使用Object类型作为e参数时:

public void run(Object e) {
    instance.run(e);
    //       ^^^
    // The method run(capture#3-of ?) in the type MyInterface<capture#3-of ?> is not applicable for the arguments (Object)
}
Run Code Online (Sandbox Code Playgroud)

我认为问题出在这个private MyInterface<?> instance领域:我需要知道实例如何参数化,使用类似的东西private MyInterface<T> instance,但我找不到工作的解决方案......

总之,我被卡住;)


PS:因为run方法体可能很长,我试图避免枚举中的匿名类:

public enum MyEnum {

    MY_CLASS_1 {
        /* any method, etc. */
    },

    MY_CLASS_2 {
        /* any method, etc. */
    },

}
Run Code Online (Sandbox Code Playgroud)

MyEnum 然后变得完全不可读.

Cos*_*atu 5

这是不可能的.这是我觉得最烦人的枚举限制之一,但你所能做的只是尝试解决它(正如你在5.0之前的Java中所做的那样).

只有枚举本身可以实现接口,并且必须在枚举级别指定泛型,因此Object在您的情况下,仅适用于这两者的常用接口或某些通用接口.

run()在枚举本身内声明要以多态方式处理的任何方面(在您的示例中为方法)(并覆盖每个常量中的行为)通常是最佳解决方法.当然,您需要放松您的类型安全要求.

如果你想保持这些策略分离,你仍然需要run(Object)在枚举中使用一个方法,并且在每个常量中使用一些显式强制转换来定义,因为你根本不能为每个枚举实例提供不同的方法签名(或者即使你可以,他们赢了从外面看不出来.


提示如何欺骗编译器,如果你真的想这样做而不是为每个实例重新设计或显式转换:

enum MyEnum implements MyInterface<Object> {
    MY_CLASS_1(new MyClass1()),
    MY_CLASS_2(new MyClass2());

    // you may also drop generics entirely: MyInterface delegate
    // and you won't need that cast in the constructor any more
    private final MyInterface<Object> delegate;

    MyEnum(MyInterface<?> delegate) {
        this.delegate = (MyInterface<Object>) delegate;
    }

    @Override
    public void run(Object e) {
        delegate.run(e);
    }
}
Run Code Online (Sandbox Code Playgroud)

ClassCastException如果您尝试使用MyEnum.MY_CLASS_1.run()除了之外的其他内容,上面的内容将起作用并且您将获得(如预期的那样)SomeOtherClass1.