对枚举进行子类化

时间:2011-01-05 14:12:16

标签: java inheritance enums

有一种简单的方法来创建Java enum的子类吗?

我问这个是因为我喜欢其中10个实现相同的接口,但它们对某些方法也有相同的实现,所以我想通过将所有相同的实现放在扩展{{1的中间对象中来重用代码它也是我需要的所有其他人的超类。

也许它不像我想的那么简单?

提前感谢

7 个答案:

答案 0 :(得分:18)

你不能这样做,因为语言不允许你。并且出于一个很好的逻辑原因:如果你能够从子类中删除某些枚举值,而不是添加新的枚举值,那么继承枚举只会有意义。否则你会破坏Liskov Substitution Principle

这简要说明每当预期超类的实例时,子类的每个实例都应该是可接受的。如果你在枚举子类中添加一个新的枚举成员,那么只知道超级枚举的人就不能接受它。

有关详情和可能的替代方案,请参阅this earlier answer of mine

在你的具体案例中,@ Jason的建议可能会提供一个很好的解决方案(+1给他: - )

更新到@DrainDog的评论

好点,我上面有点草率:-)实施方面你是对的。但是,从逻辑的角度来看,枚举类型由其有效值集完全描述。通常,正确的子类是其超类的特化。换句话说,有效子类实例的集合(应该)始终是超类实例集的子集(每只狗都是动物,但不是每只动物都是狗。)

答案 1 :(得分:11)

  

我问这个是因为我喜欢其中10个实现相同的接口,但它们对某些方法也有相同的实现,所以我想通过将所有相同的实现放在扩展Enum的中间对象中来重用代码也是我需要的所有其他人的超类。

如何使用静态助手类?

interface Animal
{
    public void speak();
}

class AnimalHelper
{
    public static void speakHelper(Animal animal) {
        // common methods here
    }
}

enum Dog implements Animal { SCHNAUZER, LABRADOR, ST_BERNARD, DACHSHUND;
    @Override public void speak() {
        AnimalHelper.speakHelper(this);
    }
};

enum Bird implements Animal { OWL, FINCH, DUCK, GOOSE; }
    @Override public void speak() {
        AnimalHelper.speakHelper(this);
    }
};

答案 2 :(得分:4)

使用Java 8,您可以使用default methods将共享实现放在界面中。

public class DefaultMethodOnEnumInterface {

    public interface Greeter {

        default public void greet() {
            System.out.println("Hello, world!");
        }
    }

    public enum Greeters implements Greeter {
        A,
        B;
    }

    public static void main(String[] args) {
        Greeters.A.greet();
        Greeters.B.greet();
    }
}

如果需要访问Enum类实现的方法,请将签名添加到界面:

public interface Greeter {

    default public void greet() {
        System.out.println("Hello, world! This is " + name());
    }

    /**
     * @see Enum#name()
     */
    public String name(); // implemented by Enum
}

答案 3 :(得分:2)

虽然Java中有proposals for abstract enums,但其好处被认为太低而不能超过成本。你必须坚持使用转发方法调用。

答案 4 :(得分:2)

尝试使用Apache commons包中的Enums,您可以在其中继承Enums。 不知道这对你有帮助。

答案 5 :(得分:0)

该语言不允许您这样做,因为Enums旨在有效地表示枚举值,而不是用于实现代码。尝试使用其他模式,如静态助手(实用程序)类。

答案 6 :(得分:0)

@Jason S提供了一个很好的回复,但静态方法会让你失去OOP的潜力。

代表团怎么样?我的意思是:

  1. 定义一个公共接口“I_A”,您可以在其中定义所有getter / setter和所有其他方法。

  2. 定义一个“类似结构”的类“S_C”:它只实现getter和setter,其他方法都是空的,因为没用。

  3. 为了使你的枚举更短(就代码行而言),定义第二个接口“I_A_Delegating”,它扩展了第一个接口,有一个额外的getter / setter,类型为“I_A”(它是我们的委托者)和,多亏了Java的默认方法,将getter / setter定义为调用委托者的getter / setter。

  4. 您的所有枚举都实现了“I_A_Delegating”,并且本地实例为“S_C”

  5. 代码示例:

    public class EnumFakeExtension{
         /**"I_A"*/
         public static interface CommonInterface{
               public Object getFieldOne();
               public Object getFieldTwo();
    
               public void setFieldOne(Object o);
               public void setFieldTwo(Object o);
    
               public void someMethod();
         }
    
         /*"S_C"*/
         public static class CommonDelegator_FieldKeeper implements CommonInterface{
             Object oOne, oTwo;
               public Object getFieldOne(){ return oOne; }
               public Object getFieldTwo(){ return oTwo; }
    
               public void setFieldOne(Object o){ oOne = o; }
               public void setFieldTwo(Object o){ oTwo = o; }
    
               public void someMethod(){ /*empty*/ }
         }
    
    
         /**"I_A_Delegating"*/
         public static interface CommonInterface_Delegating extends CommonInterface{
             public CommonInterface getDelegate();
             public void setDelegate(CommonInterface delegator);
    
             /**Just to simplify*/
             public default void setDefaultDelegate(CommonInterface delegator){
                 setDelegate( new CommonDelegator_FieldKeeper() );
             }
    
    
             public default Object getFieldOne(){ return getDelegate().getFieldOne(); }
             public default Object getFieldTwo(){ return getDelegate().getFieldTwo(); }
    
             public default void setFieldOne(Object o){ getDelegate().setFieldOne(o); }
             public default void setFieldTwo(Object o){ getDelegate().setFieldTwo(o); }
         }
    
    
        /*the enums, now*/
    
        public static enum EnumFirst implements CommonInterface_Delegating{
            FieldA, FieldB, FieldC;
    
            EnumFirst (){
                setDefaultDelegate();
            }
            final CommonDelegator_FieldKeeper delegator;
    
            public CommonInterface getDelegate(){ return delegator; }
            public void setDelegate(CommonInterface delegator){ this.delegator=delegator; }
    
    
            public void someMethod(){
                /*do what You need*/
            }
        }
    
    
        public static enum EnumSecond implements CommonInterface_Delegating{
            FieldA, FieldB, FieldC;
    
            EnumSecond (){
                setDefaultDelegate();
            }
            final CommonDelegator_FieldKeeper delegator;
    
            public CommonInterface getDelegate(){ return delegator; }
            public void setDelegate(CommonInterface delegator){ this.delegator=delegator; }
    
            public void someMethod(){
                /*do what You need, again*/
            }
        }
    }