2012-04-18 152 views
0

我有一个要求在Java中嵌套枚举。不过,在Stackoverflow和更大的Web上寻找时,我发现似乎没有关于嵌套枚举的通用约定。我见过很多不同的解释,但没有符合我的需要。嵌套树结构像Java中的枚举 - 对通常嵌套枚举Q和As的不同看法

现在让我们来讨论我的要求开始:

我需要枚举允许的命名约定,在我的Java应用程序的事件类型简单的树型结构。例如

Event.Draw.Square; 
Event.Draw.Circle; 
Event.Draw.Triangle; 
Event.Draw.Poly; 
Event.Draw.Line; 

Event.File.Load; 
Event.File.Save; 

Event.Screen.Zoom; 
Event.Screen.Flip; 

Event.Ui.New; 
Event.Ui.Close; 

我如何设想这在代码将是以下,但显然它不正确。任何指针如何获得这与枚举?

private enum event 
{ 
    Draw {Square, Circle, Triangle, Poly, Line}, 
    File {Save, Save_As, Load}, 
    Screen {Zoom, Flip, Rotate_CW, Rotate_CCW}, 
    Ui {New_Workspace, Close} 
} 

然后,我想要一个case语句或条件结构能够说事Event.Screen,或Event.Screen.Zoom。以下列方法为例:

public void evenTriggered(Event event) 
{ 
    switch (event) 
    { 
    case Event.Draw: 
      drawEvent(event.Draw); 
    case Event.UI: 
      uiEvent(event.Ui); 
    case Event.Screen: 
      screenEvent(event.Screen); 
    case Event.File 
      fileEvent(event.File); 
    default: ;//do nothing 

    }//end switch 
}//end eventTriggered 


public void drawEvent(Event.Draw event) 
{ 

    switch(event.draw) 
    { 
    case Event.Draw.Square: 
      workspace.addSquare(); 
     break; 
    case Event.Draw.Circle: 
      workspace.addCircle(); 
     break; 
    case Event.Draw.Triange: 
     workspace.addTriangle(); 
     break; 
    default: ;//do nothing 

    };//end switch 

}//end drawEvent 

感谢您花时间阅读我的文章,我期待您的建议。

Andrew。

回答

1

为什么你需要嵌套的枚举?在我看来,你所做的就是反OOP。你应该有一个基类Event,让Draw,File,UI和Screen类继承它,然后使用你的枚举来最终声明特定事件的类型,如果你必须的话(对于DrawEvent,FileEvent等等)。另一种选择是静态整数,另一种选择是甚至使“最具体”事件类型为另一类。你必须执行以下操作:

public void drawEvent(DrawEvent event) 
{ 

    switch(DrawEvent.type) // type is of datatype DrawEventType, an enum 
    { 
    case DrawEventType.Square: 
      workspace.addSquare(); 
      break; 
    case DrawEventType.Circle: 
      workspace.addCircle(); 
      break; 
    } //etcetera 
} 

或者静态的整数:

public void drawEvent(DrawEvent event) 
{ 

    switch(DrawEvent.type) // type is one of the DrawEvent static integers 
    { 
    case DrawEvent.SQUARE: 
      workspace.addSquare(); 
      break; 
    case DrawEvent.CIRCLE: 
      workspace.addCircle(); 
      break; 
    } //etcetera 
} 
+0

我想集中的事件在我的应用程序处理。所以UI的所有部分都是松散耦合的。这将使类能够将一个调用传递给事件处理程序suh,如:eventH.fireEvent(Event.draw.circle);然后,我可以记录日志,并将用户的交互存储在类别中以供日后数据挖掘。 – 2012-04-18 22:05:46

+0

那又如何避免你说'eventH.fireEvent(new DrawEvent(DrawEventType.Circle))'? – MarioDS 2012-04-18 22:11:38

+0

我想在应用程序中集中事件处理。所以UI的所有部分都是松散耦合的。 UI元素只能通过Singleton事件处理程序类来耦合。这将使类能够将一个调用传递给事件处理程序suh,如:eventH.fireEvent(Event.draw.circle)。 UI组件中的监听器然后可以在偶数处理器中注册所有EventDraw类型或Event.File的事件。我不认为这是一个反OO的想法,使用逻辑明确的枚举也是。 – 2012-04-18 22:11:40

2

嵌套枚举才有意义,如果你也有一个is a descendant of操作。这是你在第一个代码示例中提出的建议。内置的Java枚举实现中没有这样的事情,我看不出它会如何适应。

然而,你可以自由地实现你自己的类枚举类,有一个私有构造函数和public static final实例,就像我们在enum被添加到Java之前那样。有几个警告,如序列化,但它是可行的。

你也可以这样做:

public enum Foo { 

EVENT, 
EVENT_DRAW, 
EVENT_DRAW_CIRCLE; 

public boolean isDescendantOrSelf(Foo other) { 
    return other.name().startsWith(this.name()); 
} 

} 

它并不完美,因为你将不能够在开关/ case语句使用它们,但它确实给你的单位枚举值基于一个树状结构他们的名字。 (但不要用我的实现,这还不够好,我只是想表明的概念。)

+0

而“是后裔”的意思是:继承。 – MarioDS 2012-04-18 21:37:31

+0

@Mario De Schaepmeester如果我们坚持OP概述的语法,那么是的。但是有很多方法来表示一棵树。 – biziclop 2012-04-18 21:43:44

0

确定好后收到的意见我做beleive我有一个可行的解决方案,我的要求,我想分享和你。

基本的解决方案是创建一个包含两个都是枚举的字段的对象。一个类别和一个事件。然后,我可以为每个类别(事件配对)创建对象的公共静态常量实例。通过使构造函数保持私有状态,实例不能在外部进行,从而错误地将选项限制为仅定义为常量和公共的选项。

我现在可以在一个EventType类型中保存这些常量实例的任何一个。对我而言,此事件类型将保存在Event对象中,该对象将与所有UI元素将注册的中央事件系统一起使用,以接收诸如redraw()等应用程序范围事件通知。

public class EventType 
{ 
    public enum EventCategory{Draw, File, Screen, UI}; 

    public enum Event {Load, Save, Circle, Square, Triangle, Poly, Line, Flip, Zoom, Close,NewWorkspace}; 

    public final EventType FILE_LOAD = new EventType(EventCategory.File, Event.Load); 
    public final EventType FILE_SAVE = new EventType(EventCategory.File, Event.Load); 
    public final EventType DRAW_CIRCLE = new EventType{EventCategory.Draw, Event.Circle}; 
    public final EventType DRAW_SQUARE = new EventType{EventCategory.Draw, Event.Square}; 
    public final EventType DRAW_TRIANGLE = new EventType{EventCategory.Draw, Event.Triangle}; 
    public final EventType DRAW_POLY = new EventType{EventCategory.Draw, Event.Poly}; 
    public final EventType DRAW_LINE = new EventType{EventCategory.Draw, Event.Line}; 
    public final EventType SCREEN_FLIP = new EventType{EventCategory.Screen, Event.Flip}; 
    public final EventType SCREEN_ZOOM = new EventType{EventCategory.Screen, Event.zoom}; 
    public final EventType UI_CLOSE = new EventType{EventCategory.UI, Event.Close}; 
    public final EventType UI_NEW_WORKSPACE = new EventType{EventCategory.UI, Event.NewWorkspace}; 

    public Event event; 
    public EventCategory category; 

    private EventType(EventCategory cat, Event evt) 
    { 
     event = evt; 
     category = cat; 
    }//end constructor 

}//end class 
0

你可以做类似于我对ID3 Java Enum Tree的回答。你可能需要一个父指针给孩子。

+0

你的答案在哪里?您的链接转到本文,这是第一次发布。 – 2012-04-21 23:58:25

+0

对不起,有一个不好的网址。现在应该是好的。 – 2012-04-22 02:09:22

0

这可以使用您的枚举的接口来完成。

public interface Event { 
} 

public enum Draw implements Event { 
    SQUARE, CIRCLE, TRIANGLE, POLY, LINE; 
} 

public enum File implements Event { 
    LOAD, SAVE; 
} 

public enum Screen implements Event { 
    ZOOM, FLIP; 
} 

public enum Ui implements Event { 
    NEW, CLOSE; 
} 

现在你可以反应与下面的条件结构中的这些枚举事件:

public void evenTriggered(Event event) 
{ 
    if(event instanceof Draw) { 
    drawEvent((Draw)event); 
    } 
    else if(event instanceof Ui) { 
    uiEvent((Ui)event); 
    } 
    else if(event instanceof Screen) { 
    screenEvent((Screen)event); 
    } 
    else if(event instanceof File) { 
    fileEvent((File)event); 
    } 
    else { 
    //do nothing 
    } 
}//end eventTriggered 

public void drawEvent(Draw event) 
{ 

    switch(event) 
    { 
    case SQUARE: 
     workspace.addSquare(); 
     break; 
    case CIRCLE: 
     workspace.addCircle(); 
     break; 
    case TRIANGLE: 
     workspace.addTriangle(); 
     break; 
    default: ;//do nothing 

    };//end switch 

}//end drawEvent