2014-09-26 52 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