“扩展”Java枚举的替代方法

时间:2014-11-17 15:10:14

标签: java inheritance enums

我正在做一个非常愚蠢的ALife-esque应用程序,我将使用以下继承关系来创建以下类:

(摘要)Lifeform< - Plant

(摘要)Lifeform< - Animal

植物和动物有一些共同的状态,我希望这种行为能够在Lifeform中以rudamentary的形式存在。

abstract class Lifeform
{
    public static enum State
    {
        IDLE,
        DEAD
    }

    protected void someMethodSomewhere()
    {
        ....
        state = State.IDLE;   // this to be recognized by inherited creatures
        ....
    }
    protected State state;
}

class Plant extends Lifeform
{
    public Plant() { state=new Plant.State(); }

    public static enum State extends Lifeform.State  // (can't)
    {
        FEEDING,
        REPRODUCING,
    }
}

class Animal extends Lifeform
{
    public Animal() { state=new Animal.State(); }

    public static enum State extends Lifeform.State  // (can't)
    {
        FEEDING,
        FORAGING,
        FLEEING,
        GROUPING,
        REPRODUCING
    }

    // elsewhere in some method
    public void someMethod()
    {
        switch(state)
        {
            case IDLE: (...)     // from Lifeform.State
            case FEEDING: (...)  // from Animal.State
            case DEAD: (...)
            ....
        }
    }
}

在后来的(1.5+)java中是否有设施允许类似的内容,或者我最好将这种状态层次结构嵌入其自己的传统类中?

2 个答案:

答案 0 :(得分:1)

我不认为这是一个枚举问题,因为它是一个状态机问题。

您的名字为State,这对我来说意味着您实际上正在使用状态机。我不会使用enum来实际建模一个合适的状态机。

从您在问题中发布的,它们也意味着有限的状态机。我认为你只是围绕这些enums实现某种状态机作为最终结果,并且应该继续并从最终结束的地方开始。

我过去使用state machine compiler效果很好,只是简单地创建和管理状态转换。

Ragel看起来也是一个很好的解决方案。

你可以做你想做的唯一方法是推出你自己的1.4之前的TypeSafe Enum

在Java以enum作为类型之前,我在IDE中使用了Type Safe Enum Pattern模板来创建实际上更加丰富的语言结构实现。

它本质上只是一个带有final个实例成员的Java类,以及一个private构造函数和public final static个实例。

我仍然会警告,由于一个很好的理由不允许延长enum,并且试图解决它可能会让你更难以解决。

答案 1 :(得分:0)

以下是我多年来使用的解决方案,以防有人帮忙。我稍微改写了一下。

注意:它故意不实现价值支持。这不是一个很难改变,坦率地说,我不会使用它们,所以我把它拉了出来。我还从原来的古老版本重写了它。

注意:我主要在这里提供它,因为它包含toString()支持以从任何子类产生字段名称(无论您使用了什么)。

由于访问限制导致灾难性(执行结束)错误,我还指定了字段错误。您可以将其修改为您选择的任何异常处理,但我建议您保持原样。

package tgm.utils;

import java.lang.reflect.Field;


public abstract class InheritableEnum
{
    protected InheritableEnum() {}

    public String toString()
    {
        String returnStr = "Unknown InheritableEnum["+super.toString()+"]";

        Field[] fields = this.getClass().getFields();        
        for (Field f : fields)
        {
            try
            {
                if (f.get(this) == this)
                {
                    returnStr = f.getName();
                    break;
                }
            }
            catch(IllegalAccessException e)
            {
                System.err.println("Illegal access on field["+f+"]");
                e.printStackTrace();
                System.exit(-1);
            }
        }

        return returnStr;
    }
}

然后你会同样使用它:

public class State extends InheritableEnum
{
    public static final State DEAD    = new State();
    public static final State EATING  = new State();
    public static final State GROWING = new State();
}