2014-09-26 67 views
0

我们正在使用libgdx为Android设备创建游戏原型。对于屏幕管理,我们使用带有屏幕名称的枚举来获取ScreenManager类的抽象层。所以你可以做这样的事情来显示一个新的屏幕,并隐藏旧屏幕:ScreenManager.getInstance().show(Screens.LOGIN);Java - 在其内部使用枚举值

现在我们想要使用设备的后退按钮跳回屏幕或退出应用程序。所以我们想在每个枚举值中创建一个字段来声明parentScreen并在按下后退按钮时使用它。不幸的是,它不能在自己内部使用枚举自己的字段,我们得到以下错误:Cannot refer to the static enum field Screens.LOGIN within an initializerprotected Screens parentScreen = Screens.LOGIN;。也许任何人都有一个想法如何解决这个问题。

下面是实际的枚举:

/** 
* Used to hide actual implementations of Screen interface and expose only "pointer objects". 
* All of them are declared with package-private class modifier. 
*/ 
public enum Screens { 

SPLASH { 
    @Override 
    protected Screen getScreenInstance(MyGdxGame game) { 
     return new SplashScreen(game); 
    } 
}, 

LOGIN { 
    @Override 
    protected Screen getScreenInstance(MyGdxGame game) { 
     return new LoginScreen(game); 
    } 
}, 

GAME { 
    protected Screens parentScreen = Screens.LOGIN; 

    @Override 
    protected Screen getScreenInstance(MyGdxGame game) { 
     return new GameScreen(game); 
    } 
}, 

CREDITS { 
    protected Screens parentScreen = Screens.LOGIN; 

    @Override 
    protected Screen getScreenInstance(MyGdxGame game) { 
     return new CreditsScreen(game); 
    } 
}; 

protected Screens parentScreen = null; 

/** Every enum member musts override this method and it will be visible only inside the package */ 
protected abstract Screen getScreenInstance(MyGdxGame game); 
} 

这个功能应该显示屏幕父:

/** 
* Execute when the user clicks the back button 
* Default called by the AbstractScreen Class 
*/ 
public void backButton() { 
    this.show(this.currentScreen.parentScreen); 
} 

感谢您的建议提前!

+2

我的建议是:当一个枚举开始看起来太像一个普通的类,使用一个普通的类。您可以在该类中定义该类的公共静态实例,因此您仍然可以将它们称为Screens.LOGIN。 – Davio 2014-09-26 12:06:00

+0

即使您以这种方式成功强制使用枚举概念,由于它的刚性,它很可能会在后面反弹。您应该尝试更好地确定业务逻辑必须执行的操作以及它的工作原理。 – allprog 2014-09-26 12:15:01

+0

感谢您的建议 - 如果枚举变得更加复杂,并获得一些逻辑,我会考虑使用类。 – Rubberducker 2014-09-26 12:55:23

回答

2

有多种可能性。我最喜欢的是使用一个构造函数,因为它较少的文本,但有点更容易阅读:

public enum Screens { 

SPLASH(Screens.LOGIN) { 
    @Override 
    protected Screen getScreenInstance(MyGdxGame game) { 
     return new SplashScreen(game); 
    } 
}, 

LOGIN(null) {//...} 

;//this semi-colon is expected after the enum values 

private final Screens parentScreen; 

Screens(Screens parent){//Constructor 
    parentScreen = parent; 
} 

public Screens getParentScreen(){ 
    return parentScreen; 
} 

protected abstract Screen getScreenInstance(MyGdxGame game); 

另一种解决方案是申报一个抽象方法getParentScreen():

public enum Screens { 

SPLASH { 
    @Override 
    protected Screen getScreenInstance(MyGdxGame game) { 
     return new SplashScreen(game); 
    } 
    @Override 
    protected Screen getParentScreen() { 
     return Screens.LOGIN; 
    } 
}, 
//... 
; 

protected abstract Screen getScreenInstance(MyGdxGame game); 
protected abstract Screen getParentScreen(); 
1

你可以用这个尝试:

/** 
* Used to hide actual implementations of Screen interface and expose only "pointer objects". 
* All of them are declared with package-private class modifier. 
*/ 
public enum Screens { 

SPLASH { 
    @Override 
    protected Screen getScreenInstance(MyGdxGame game) { 
     return new SplashScreen(game); 
    } 
}, 

LOGIN { 
    @Override 
    protected Screen getScreenInstance(MyGdxGame game) { 
     return new LoginScreen(game); 
    } 
}, 

GAME { 
    @Override 
    protected Screen getParentScreen() { 
     return Screens.LOGIN; 
    } 

    @Override 
    protected Screen getScreenInstance(MyGdxGame game) { 
     return new GameScreen(game); 
    } 
}, 

CREDITS { 

    @Override 
    protected Screen getParentScreen() { 
     return Screens.LOGIN; 
    } 


    @Override 
    protected Screen getScreenInstance(MyGdxGame game) { 
     return new CreditsScreen(game); 
    } 
}; 

protected Screen getParentScreen() { 
    return null; 
} 

/** Every enum member musts override this method and it will be visible only inside the package */ 
protected abstract Screen getScreenInstance(MyGdxGame game); 
} 

通过使用你克服限制的方法(而不是字段)。

注意 另外,做这样的事情:

public enum X { 
    VALUE1 { 
    protected String fieldYYY = ...; 
    } 

    protected String fieldYYY = ...; 
} 

是不是真的一个很好的事情。当枚举被编译时,它们大致被转换​​为具有具体子类X.VALUE1,X.VALUE2,X.VALUEN的抽象超类X.如果你在超类(X)中声明了一个字段,然后在你的子类中再次声明它你并没有真正覆盖它,但是你最终得到了两个字段,它们的名字是相同的......第一个字段(X中的那个,超类)被范围隐藏......但它在那里!如果这样的字段是可变的 - 但不是枚举的话 - 你可能会释​​放混乱(一些代码引用了你的超类中的一些,而另一些则是你拥有的)。

+0

@SME_Dev解决方案实际上更加紧凑和整齐 – Claudio 2014-09-26 12:26:18

+0

感谢您的回答! – Rubberducker 2014-09-26 12:57:00