枚举的子类化

发布于 2024-10-10 15:02:43 字数 212 浏览 3 评论 0原文

有没有一种简单的方法来子类 Java enum

我问这个问题是因为我有大约 10 个实现相同接口的代码,但它们对某些方法也有相同的实现,因此我想通过将所有相同的实现放置在扩展 Enum 它也是我需要的所有其他类的超类。

或许事情并没有我想象的那么简单?

提前致谢

is there a simple way to subclass a Java enum?

I ask this because I have like 10 of them that implement the same interface but they also have the same implementation for some methods so I would like to reuse the code by placing all the same implementations in middle object that extends Enum and it is also the superclass of all the others I need.

Maybe it is not so straightforward as I think?

Thank in advance

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(7

吝吻 2024-10-17 15:02:43

你做不到,因为语言不允许你这样做。出于一个很好的逻辑原因:只有当您可以从子类中删除一些枚举值而不是添加新的枚举值时,子类化枚举才有意义。否则你就会违反里氏替换原则

简而言之,只要需要超类的实例,子类的每个实例都应该是可接受的。如果您在枚举子类中添加新的枚举成员,那么只知道超级枚举的人显然无法接受。

有关更多详细信息和可能的替代方案,请参阅我之前的回答

在你的具体情况下,@Jason的建议可能会提供一个很好的解决方案(对他来说+1:-)

更新@OrangeDog的评论

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

You can't do it, since the language does not allow you. And for a good logical reason: subclassing an enum would only make sense if you could remove some enum values from the subclass, not add new ones. Otherwise you would break the Liskov Substitution Principle.

This in brief states that every instance of a subclass should be acceptable whenever an instance of a superclass is expected. If you add a new enum member in an enum subclass, that clearly can't be accepted by someone knowing only the super enum.

For more details and possible alternatives, see this earlier answer of mine.

In your concrete case, @Jason's suggestion may offer a good solution (+1 for him :-)

Update to @OrangeDog's comment

Good point, I was a bit sloppy above :-) Implementation-wise you are right. However, from the logical point of view an enum type is fully described by the set of its valid values. And generally, a proper subclass is a specialization of its superclass. In other words, the set of valid subclass instances is (should be) always a subset of the superclass instance set. (Every dog is an animal, but not every animal is a dog.)

来日方长 2024-10-17 15:02:43

我问这个问题是因为我有大约 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);
    }
};

I ask this because I have like 10 of them that implement the same interface but they also have the same implementation for some methods so I would like to reuse the code by placing all the same implementations in middle object that extends Enum and it is also the superclass of all the others I need.

How about using a static helper class?

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);
    }
};
2024-10-17 15:02:43

使用 Java 8,您可以使用 默认方法。

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
}

With Java 8 you can put the shared implementation in the interface using 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();
    }
}

If access to methods implemented by the Enum class is required, add the signature to the interface:

public interface Greeter {

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

    /**
     * @see Enum#name()
     */
    public String name(); // implemented by Enum
}
温柔戏命师 2024-10-17 15:02:43

尝试使用 Apache commons 包中的 Enums,您可以在其中子类化 Enums。
不知道这是否会帮助你。

Try using Enums from Apache commons package, where you can subclass Enums.
Dont know if this will help you.

深府石板幽径 2024-10-17 15:02:43

虽然 Java 中已有关于抽象枚举的提议,但人们认为其好处还远远不够。太低而无法抵消成本。您必须坚持转发方法调用。

Whilst there have been proposals for abstract enums in Java, the benefits are considered far too low to outweigh the costs. You'll have to stick with forwarding method calls.

暮光沉寂 2024-10-17 15:02:43

该语言不允许您这样做,因为枚举是为有效表示枚举值而设计的,而不是为了实现代码。尝试使用另一种模式,例如静态帮助器(实用程序)类。

The language does not allow you to do so, as Enums are designed for representing enumerated values efficiently, not for implementing code. Try using another pattern like a static helper (utility) class.

纵山崖 2024-10-17 15:02:43

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

代表团呢?我的意思是:

  1. 定义一个通用接口“I_A”,在其中定义所有 getter/setter 和所有其他方法。

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

  3. 为了使您的枚举更短(就代码行而言),请定义第二个接口“I_A_Delegating”,它扩展了第一个接口,并具有一个“I_A”类型的附加 getter/setter(它是我们的委托者),并且感谢Java 的默认方法,将 getter/setter 定义为调用委托者的 getter/setter。

  4. 您的所有枚举都实现“I_A_Delegating”并具有“S_C”的本地实例

代码示例:

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*/
        }
    }
}

@Jason S has offered a good reply, but the static method make you lose the OOP's potentialities.

What about delegation? I mean:

  1. Define a common interface "I_A" where you defines all getters/setters and all other methods.

  2. Define a "struct-like" class "S_C" : it implements only the getters and setters, other methods are empty because are useless.

  3. To make your enumerations shorter (in terms of lines of code), define a second interface "I_A_Delegating" that extends the first ones, has an additional getter/setter of type "I_A" (it's our delegator) and, thanks to Java's default methods, define the getter/setter as calling the delegator's getter/setter.

  4. All of your enumerations implements "I_A_Delegating" and has a local instance of "S_C"

Code example:

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*/
        }
    }
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文