2014-12-01 123 views
2

所以我試圖做一個簡單的RPG般的基於文本的遊戲來鞏固我的一些研究,我想知道如何最好的方式來實現這種類型的設置是:類層次結構和設置

接口稱爲戰鬥機>由AbstractFighter實施> MagicFighter和StrengthFighter擴展AbstractFighter。 (原本MagicFighter和StrengthFighter有自己的接口,具有額外的獨特行爲),但...

現在,令人困惑的是我希望玩家能夠在這兩種戰鬥機之間進行選擇,然後將其存儲在列表(戰鬥機)。所以很顯然,我得到的類型總是戰鬥機(它必須是因爲我不知道用戶將選擇哪種戰鬥機的實現),我只能調用在戰鬥機接口中的方法。我可以做的一件事是每次我需要調用不同Fighter實現所特有的方法時,爲玩家選擇和下注而寫入檢查。但是這意味着很多重複的代碼,並且聽起來很亂= /。

另一種可能性是運行檢查並根據用戶的選擇將用戶添加到列表(StengthFighter)或列表(MagicFighter),但最終這與前面的「解決方案」具有完全相同的問題。

我能想到的最後一件事就是嘗試和反映Fighter的每個實現,以便每個行爲都有一個版本。因此,例如 void regen();在戰鬥機界面中,然後對StrengthFighter和MagicFighter採用不同的方式(魔法戰士可以恢復法力值,力量戰士可能會在他使用攻擊時恢復憤怒()(這是由於ManaFighter需要實施regen() ,但內StrengthFighter使用,這將是私人)

不管怎麼說,你現在可能已經得到的要點,所以金正日節省更多textwalling

沸騰什麼下來;這是一大敗筆我或者這僅僅是面向對象編程的必然性呢?我的意思是,在一天結束時,如果Java要求用戶做出決定,Java如何知道結果需要的類型(以及因此使用它的方法)確定類型

+0

Make Fighter有一個公共職業,作爲樣板戰鬥機,並擴展/重寫MagicFighter和StrengthFighter特定的方法。另一種選擇是隻讓一個基於枚舉類型處理所有事情的Fighter類。對面向對象很好,但是當它像你提交時一樣令人困惑的時候,可以減少一些複雜性並保持簡單。 – Compass 2014-12-01 21:36:36

+0

當用戶選擇他的類型時,只需調用新的MagicFighter(),然後它自然會調用特定的方法? – realUser404 2014-12-01 21:40:35

回答

0

這是基於您的問題解釋的粗略類實現。你有一個界面,然後是一個實現,然後個人類型的原始定義感覺很複雜。相反,我們希望與個人Fighter s合作,而不是他們的表述。

class Fighter { 
    int hp; 

    void attack() { 

    } 

    void move() { 

    } 

    void regen() { 
     hp++; 
    } 
} 

class MagicFighter extends Fighter { 
    int mana; 

    @Override 
    void regen() { 
     mana++; 
     //we don't regen hp because we're magic-type. 
    } 
} 

class StrengthFighter extends Fighter { 
    int rage; 

    @Override 
    void attack() { 
     super.attack(); 
     specialRegen(); 
    } 

    void specialRegen() { 
     rage++; 
    } 

    @Override 
    void regen() { 
     // does nothing 
    } 

    void berserk() { 
     rage--; 
    } 
} 

在這種情況下,我們可以存儲的Fighter

List<Fighter> fighters = new List<>(); 

一個列表時,我們要創建一個新的戰鬥機,我們會確定用戶想要什麼,並添加到戰士的名單。

if (selection.equals("StrengthFighter")) { 
     Fighter fighter = new StrengthFighter(); 
     fighters.add(fighter); 
    } 

然後,我們將所有的方法調用正常。這兩個類之間共享的任何內容都不會被覆蓋,例如Fighter.move。任何不適用於一種類型的內容都將被覆蓋,如StrengthFighter.regen。任何具有針對特定類型的特殊附加功能的實施都將實施附加功能並撥打super電話,如StrengthFighter.attack

基本上,您已經有了正確的想法,但基本上,您希望Fighter儘可能多地執行共享工作,然後根據幕後類型實施各個操作。如果有什麼需要檢查的類型,它需要一些獨特的,以該類型戰鬥機,如StrengthFighter.berserk

這減少了需要檢查的類型除非他們真正的問題。

+0

嘿,那裏,謝謝你花時間瀏覽我的問題並提供答案。因此,最終要調用berserk()例如我需要沮喪,但只有當真正需要時? – FinalFind 2014-12-01 21:58:10

+0

@FinalFind是的。如果一個普通的'戰鬥機'不知道狂暴,你不能真的叫它。當然,你也可以編寫一個名爲'specialAbility'方法,但若有特殊功能適用,所以在最後,躲在要瘋搶調用沒有幫助的事實,你不知道這問題。 – Compass 2014-12-01 22:23:26

0

我認爲你唯一的戰鬥機> FighterImpl。其他工作人員應分別實施:武器,防具,能力,等等​​

在創建您授予與能力+武器(通過能力受限)+津貼的戰鬥機。然後所有的戰士生活在相同的條件下。

interface Fighter { 
    int getSpeed(); // base fighter speed per time unit 
    Armor getArmor(); 
    Weapon getWeapon(); 
    Damage attack(Fighter enemy); // animate + apply damage 
    Position move(); 
    List<Perks> getPerks(); 
    List<Ability> getAbilities(); 
} 

interface Weapon { 
    DamageType getDamageType(); 
    int getDamage(); 
    void animateHit(Fighter enemy); 
} 

abstract class AbstractWeapon implements Weapon { 
    ... 
} 

abstract class MeleeWeapon extends AbstractWeapon { 
    ... 
} 

abstract class MagicWeapon extends AbstractWeapon { 
    ... 
}