对枚举值进行子类化

时间:2016-01-30 21:54:12

标签: java inheritance enums

我希望能够在枚举中对一些值进行子类化,以便我不必过多地重复代码。有什么方法可以做到这一点吗?这是我想要实现的一个例子,Eclipse很快告诉我这是一个令人厌恶的事情:

public enum Foo {
    BAR {
        @Override
        public void taskA() {
            System.out.println("A");
        }

        @Override
        public void taskB() {}
    },
    BAZ extends BAR {
        @Override
        public void taskB() {
            System.out.println("B");
        }
    };

    public abstract void taskA();
    public abstract void taskB();
}

BAR只会执行taskA而空taskB,而BAZ会有两种方法 - BAR的{​​{1}}实现1}},以及它自己的taskA实现。

我没有在声明后更改枚举的值,为什么这不起作用?我可以在taskB内调用BAR的{​​{1}}方法,为什么我不能这样做?

2 个答案:

答案 0 :(得分:2)

枚举 - 常量是对象(实例),而不是类。你只能将类子类化。

然而即使这样也行不通:你只能扩展任何内部类的枚举。

您必须为您的用例找到另一种解决方案。你可以:

  • 对共享代码使用静态方法
  • 在BAZ致电BAR.taskA()
  • 使taskA不抽象并将代码放在那里
  • 使用常规常量,而不是枚举

但我最喜欢的是:

  • 注入行为而不是覆盖!

示例代码:

class Behavior {
    public static Runnable A = new Runnable() {
        public void run() {
            System.out.println("A");
        }
    }

    public static Runnable B = new Runnable() {
        public void run() {
            System.out.println("B");
        }
    }

    public static Runnable DO_NOTHING = new Runnable() {
        public void run() {
        }
    }
}

public enum Foo {
    BAR(Behavior.A, Behavior.DO_NOTHING),
    BAZ(Behavior.A, Behavior.B);

    private final Runnable mechanismA;
    private final Runnable mechanismB;

    private Foo(Runnable mechanismA, Runnable mechanismB) {
        this.mechanismA = mechanismA;
        this.mechanismB = mechanismB;
    }

    public void taskA() {
        mechanismA.run;
    }

    public void taskB() {
        mechanismB.run;
    }
}

此解决方案的优点:

  • 代码显式定义每个枚举常量的行为 - 无隐式计算=>更容易阅读
  • 您可以在Behavior-class
  • 中使用继承
  • 您可以轻松切换behaviorA和behaviorB - 或重复使用代码

如果您有Java8可用,您甚至可以将代码缩短为:

public static Runnable A = () -> {
    System.out.println("A");
};

答案 1 :(得分:2)

  

我希望能够在枚举中为一些值创建子类,以便我   不要过多地重复代码。

在常量特定方法之间共享代码的常用方法是声明一个私有静态方法(在枚举本身或实用程序帮助程序类中),它包含您希望从常量特定方法访问的公共代码

例如......

public enum Foo {
    BAR {
        @Override
        public void taskA() {
            commonToTaskAandB();
            System.out.println("B"); 
       }

        @Override
        public void taskB() {}
    },
    BAZ {
        @Override
        public void taskB() {
            commonToTaskAandB();
            System.out.println("B");
        }
    };

    public abstract void taskA();
    public abstract void taskB();

    private static void commonToTaskAandB() {
        // shared code here
        :
        :
    }

}

请注意代码&#34; BAZ extends Bar&#34;是非法的,因为BAZ不是一种类型。 BAZ是您Enum<Foo>类型的实例。实例不能扩展另一种类型。将继承等面向对象原则应用于枚举常量是不正确的,因为在Java中,枚举常量是类的实例而不是类本身。