【问题标题】:Make super class use the Enum used by the child class让超类使用子类使用的枚举
【发布时间】:2012-01-18 23:15:09
【问题描述】:

我有

public enum BaseActions implements Actions{
    STAND (0,0,0),
    TURN (1,1,1);
    //other stuff
}

public enum CoolActions implements Actions{
   STAND (0,2,3),
   TURN(1,6,9);
   //other stuff
}

public enum LooserActions implements Actions{
   STAND (0,-2,-3),
   TURN(1,-6,-9);
   //other stuff
}

public interface Actions {
       //interface methods
}

class A {
    Actions mCurrentAction;
    protected void notifyNewAction(final Actions pAction, final Directions pDirection){
         //body of the method
    }

    public void doStuff(final Actions pAction) {
         if(pAction.getMyId() > 0)
              notifyNewAction(BaseActions.STAND, myDirection);
         else
             notifyNewAction(BaseActions.TURN, myDirection);
    }
}

class B extends A{
     public void doMyStuff() {
           doStuff(CoolActions.STAND);
     }
}

class C extends A{
     public void doMyStuff() {
           doStuff(LooserActions.STAND);
     }
}

我想让 A 在从 B 调用 doStuff 时使用 CoolActions 在从 C 调用时使用 LooserActions。 我认为我可以做到的一种方法是使用泛型,然后在 B 和 C 中使用

doStuff<CoolActions>(CoolActions.STAND)

并且在A中拥有

public void doStuff<T extends EnumActions&Actions>(final Actions pAction) {
             if(pAction.getMyId() > 0)
                  notifyNewAction(T.STAND, myDirection);
             else
                 notifyNewAction(T.TURN, myDirection);
        }

其中 EnumActions 是一个基本枚举,它只包含枚举元素的声明,仅此而已,类似于枚举的接口,但枚举不能扩展另一个类,因为它们已经扩展了 Enum,而接口不能提供我的意思。 另一种方法是让枚举实现一个 EnumActions 接口,该接口具有

public interface EnumActions {
    public <T> T getStand();
    public <T> T getTurn();
}

并且拥有

 class A {
        Actions mCurrentAction;
        protected void notifyNewAction(final Actions pAction, final Directions pDirection){
             //body of the method
        }

        public <T implements EnumActions> void doStuff(final Actions pAction) {
             if(pAction.getMyId() > 0)
                  notifyNewAction(T.getStand(), myDirection);
             else
                 notifyNewAction(T.getTrun(), myDirection);
        }
    }

public enum CoolActions implements Actions, EnumActions{
   STAND (0,2,3),
   TURN(1,6,9);
    public CoolActions getStand();
    public CoolActions getTurn();
   //other stuff
}

class B extends A{
     public void doMyStuff() {
           doStuff<CoolActions>(CoolActions.STAND);
     }
}

但是 1)我不知道它是否会起作用 2)我失去了使用枚举的优势 3)这接缝是处理这个问题的非常糟糕的方法 4)我必须写很多(每个 Y X 枚举字段不同的枚举)。我从静态最终字段更改为枚举以提高可读性和顺序,而这使事情变得更加困难。

我是否以错误的方式设计了这个?我该如何处理? 有解决此问题的首选方法吗? 谢谢

【问题讨论】:

    标签: java class inheritance enums


    【解决方案1】:

    似乎枚举没有添加任何内容,也不会做你想做的事。也许您应该只使用普通的类层次结构 - 使 BaseActionsCoolActionsLooserActions 只是实现 Actions 的类以及这些类中的 STAND 和 TURN 方法。

    【讨论】:

    • 那么,如果枚举可以被类替换并且不能执行它们的设计用途(将选择限制为仅一组变量),那么使用枚举的原因是什么?我从未使用过它们,当我第一次认为它们有用时,它们无法满足我的需求。在网上冲浪时,我发现了许多其他情况,就像我的一样。。
    • @Makers_F:枚举完全按照它们的设计目的进行。但它们不能扩展,因此不是多态的。你的设计需要多态性,所以不要使用枚举。
    【解决方案2】:

    它很丑,但它可以做你想做的事:

    interface Actions {
        int getMyId();
    }
    enum BaseActions implements Actions {
        STAND(0, 0, 0), TURN(1, 1, 1);
        BaseActions(int x, int y, int z) {}
        @Override public int getMyId() {
            return 0;
        }
    }
    enum CoolActions implements Actions {
        STAND(0, 2, 3), TURN(1, 6, 9);
        CoolActions(int x, int y, int z) {}
        @Override public int getMyId() {
            return 0;
        }
    }
    enum LooserActions implements Actions {
        STAND(0, -2, -3), TURN(1, -6, -9);
        LooserActions(int x, int y, int z) {}
        @Override public int getMyId() {
            return 0;
        }
    }
    class Directions {}
    class A {
        Actions mCurrentAction;
        protected void notifyNewAction(final Actions pAction, final Directions pDirection) {
        System.out.println(pAction+" "+pAction.getClass());
        }
        public void doStuff(final Actions pAction) {
            Directions myDirection = null;
            Enum e=(Enum)pAction;
            if(e instanceof CoolActions)
                e=CoolActions.valueOf(e.name());
            else if(e instanceof LooserActions)
                e=LooserActions.valueOf(e.name());
            if (pAction.getMyId() > 0) notifyNewAction((Actions)e, myDirection);
            else
                notifyNewAction((Actions)e, myDirection);
        }
    }
    class B extends A {
        public void doMyStuff() {
            doStuff(CoolActions.STAND);
        }
    }
    class C extends A {
        public void doMyStuff() {
            doStuff(LooserActions.STAND);
        }
    }
    public class Main {
        public static void main(String[] args) {
            A a = new A();
            a.doStuff(BaseActions.STAND);
            B b = new B();
            b.doMyStuff();
            C c = new C();
            c.doMyStuff();
        }
    }
    

    【讨论】:

    • 是的,它很丑 ;) 顺便说一句,我不会进行这种 hack,因为我会有很多动作,然后代码会变得非常庞大,并且很难维护(添加/删除操作等。)但在不同的情况下,这可能是一个很好的解决方法
    • 看起来丑陋的东西可以消失: public void doStuff(final Actions pAction) { /* 这真的能如你所愿吗? */ 方向 myDirection = null; if (pAction.getMyId() > 0) notifyNewAction(pAction, myDirection);否则 notifyNewAction(pAction, myDirection); }
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-11-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多