【问题标题】:java enums in abstract class抽象类中的java枚举
【发布时间】:2016-06-23 12:34:13
【问题描述】:

我知道 java 中的枚举以及它们是如何不可继承且是最终的等等。我一直在寻找这个,但我仍然无法找到我想要实现的替代方案。这是通用代码,尽可能简化:

实用程序

public abstract class Utility {

    public Utility() {
    }

    public abstract void run() throws Exception;
}

MyUtility1

public class MyUtility1 extends Utility {

    public MyUtility1() {
    }

    @Override
    public void run() throws Exception {
        //do something
    }
}

MyUtility2

public class MyUtility2 extends Utility {

    public MyUtility2() {
    }

    @Override
    public void run() throws Exception {
        //do something
    }
}

主要

public class Main {

    public static void main(String args[]) {
        try {
            Utility ut = null;
            if(/* something here */) {
                ut = new MyUtility1();
            } else {
                ut = new MyUtility2();
            }
            ut.run();
        } catch(MissingPropertyException e) {}
    }
}

现在我需要在 MyUtility1 和 MyUtility2 上有一组不同的常量。我会为此使用枚举:

MyUtility1

public class MyUtility1 extends Utility {

    public enum Properties {
        MONDAY("Monday"),
        TUESDAY("Tuesday");

        String property;

        Properties(String prop) {
            property = prop;
        }
    }

    public MyUtility1() {
    }

    @Override
    public void run() throws Exception {
        //do something
    }
}

MyUtility2

public class MyUtility2 extends Utility {

    public enum Properties {
        JANUARY("January"),
        FEBRUARY("February");

        String property;

        Properties(String prop) {
            property = prop;
        }
    }

    public MyUtility2() {
    }

    @Override
    public void run() throws Exception {
        //do something
    }
}

到目前为止,一切正常。我现在想念的是一种常用方法,最好在Utility 类中进行排序验证,无论调用哪个枚举。类似:

protected boolean checkProperties(Properties props) throws MissingPropertyException {
    for(Property property : props.values()) {
        /* do something */
    }
}

在超级构造器上这样称呼它:

public Utility() throws MissingPropertyException {
    checkProperties(/* here comes the child.Properties */);
}

(是的,我知道上面的代码不会编译,这只是象征性的)

有什么建议吗?如果可能,将“帮助类”解决方案留作最后的手段

【问题讨论】:

  • 那张支票对我来说毫无意义。让我怀疑 Enum 不是你在这里需要的。这些检查应该确保什么?

标签: java inheritance enums super


【解决方案1】:

看起来您想在实用程序实例中嵌入调度规则。我认为这是个坏主意。

一个更好的主意是让所有Utility 类实现RunnableCallable。将这些分配给带有规则的预定 Executor 实例。

将已完成的内容与完成的时间区分开来。您可能想要更改计划,而不必修改 Utility 实例。将该逻辑外部化并使其可配置将使其变得容易。

【讨论】:

  • 我不确定我是否理解您对“调度规则”甚至“何时完成”部分的意思。如果它的实际枚举值令人困惑,那么只需将它们重命名为 AUDI("audi")、VOLVO("volvo") 甚至 RED("red")、GREEN("green").. 它们真的不重要。 ..这里的一般想法是 ut.run() 在构造实用程序对象失败时不会被调用,因为在某处找不到枚举属性之一,并且属性取决于子实用程序类。 . 枚举是“必需”的想法是因为这些枚举值可以在其他地方使用
  • 这是我对 Utility 类的第一个想法:“看起来像 Runnable”...
  • 忘记枚举。这些枚举中有月份、日期等(顺便说一句,在别处更好地定义)。它们不依赖于 Utility 类;情况正好相反。
【解决方案2】:

在我看来,您似乎想使用泛型。

让您将属性提取到“Day”和“Month”枚举的图像,您的 Utility1 和 Utility2 类似乎是一种“实用程序”和“实用程序”

要完成您的示例,这将类似于:

Utility.java

public abstract class Utility<T> {
    protected Utility(T prop) throws Exception {
        checkProperties(prop);
    }
    public abstract void run() throws Exception;
    public abstract void checkProperties(T prop) throws Exception;
}

Utility1.java

public class Utility1 extends Utility<Day> {
    public Utility1(Day day) throws Exception {
        super(day);
    }
    @Override
    public void run() throws Exception { }
    @Override
    public void checkProperties(Day prop) throws Exception { }
}

Utility2.java

public class Utility2 extends Utility<Month> {
    public Utility2(Month month) throws Exception {
        super(month);
    }
    @Override
    public void run() throws Exception { }
    @Override
    public void checkProperties(Month prop) throws Exception { }
}

Day.java

public enum Day {
    MONDAY, TUESDAY;
}

Month.java

public enum Month implements IProperties {
    JANUARY, FEBRUARY;
}

您还可以让您的枚举实现一个接口(比如 IProperties)并使用 Utility 来强制执行更强的类型

【讨论】:

  • 我想避免复制代码,因为 checkProperties 对任何 Utility 实例都做了完全相同的事情......整个事情中唯一不同的是每个“属性”属性的实际值枚举常量
【解决方案3】:

将 checkProperties 转换为要由类实现的抽象。

 protected abstract boolean checkProperties() throws MissingPropertyException;

现在根据要求在两个类中实现 checkProperties。如果使用相同的方法进行检查,请在实用程序类中创建。

交替改变

   protected boolean checkProperties(Class<? extends Enum> clazz) throws MissingPropertyException {
           Enum[] enum =  clazz.getEnumConstants(); //Do required validation here
}

并在构造函数中调用适当的 Properties.class

public MyUtility2() {
   super(Properties.class)    
}


public Utility(Class<? extends Enum> clazz) throws MissingPropertyException {
    checkProperties(clazz);
}

作为for(Property property : props.values()) { //Cannot work for any property.

【讨论】:

    【解决方案4】:

    一个建议是让Utility 类像这样通用:

    public abstract class Utility<T extends Enum<?>> {
    
         T[] properties
         public Utility() {
             checkProperties();
         }
         protected void checkProperties() throws MissingPropertyException;
         public abstract void run() throws Exception;
    }
    

    然后像这样定义 MyUtility1 :

    class MyUtility1 extends Utility<MyProperties1> { //class body }  
    

    对于 MyUtility2 以此类推,请注意在 main 上,变量 ut 应声明为 Utility&lt;?&gt;
    此解决方案有缺点,例如,如果您在 Utility 中有一个以 T 作为参数的函数,并且您希望它是多态的,则它将无法工作。

    另一个建议是使用属性Enum&lt;?&gt;[] 而不是T[],Enum 是一个抽象类,所以这有一些问题,首先你需要在你想处理真实类型时进行转换,比如@987654328 @ 例如。

    第二个任何枚举都可以放在properties中,所以你必须创建一些函数addProperty,并且这个函数必须验证传入的属性的类型。

    我认为最好的解决方案是将枚举排除在继承之外:)。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-10-01
      • 2011-07-29
      • 2013-03-05
      • 1970-01-01
      相关资源
      最近更新 更多