2012-02-10 72 views
0

我不知道我是否選擇了一個好的標題或沒有,但我正在開發一個簡單的基於卡片的遊戲,這是我的情景:這種繼承方式錯了嗎?

我有一個名爲球員我已經實例化幾個對象類(讓我們說4)從播放器。在每一輪比賽中,我們有一種特殊類型的球員可以說SpecialPlayer即每輪中的那4名球員之一可以是SpecialPlayer。

SpecialPlayer是一個簡單的播放器加上它可以做更多的東西,可以說暫停/重新啓動遊戲。所以我從Player繼承並創建了SpecialPlayer併爲該類添加了2個方法。 問題是,當我實例化SpecialPlayer時,我將有另一個對象加上那些4個玩家對象,那好吧,但是我想能夠改變SpecialPlayer的屬性並且看到在這一輪是SpecialPlayer的Player對象上的效果

例如,每個玩家都可以獲得分數,我想看看SpecialPlayer得分並且改變分數及其對玩家對象的影響。

這裏繼承是錯誤的嗎?我是否必須在SpecialPlayer類中編寫Player類?

如果它可能會改變答案,我不得不說我正在使用紅寶石

回答

1

我將不得不與別人不同意,並告訴你這聽起來像你需要用SpecialPlayer模塊擴展您的Player實例。讓我來證明一下。假設你有一個球員類:

class Player 
    attr_accessor :game 

    def special? 
    false 
    end 
end 

所有球員都會有這些方法。讓我們創建一個新的玩家:

player = Player.new 
player.game = Game.new 
player.special? # false 

現在讓我們假設你有你的SpecialPlayer模塊:

module SpecialPlayer 
    def special? 
    true 
    end 

    def pause_game 
    game.pause 
    end 

    def restart_game 
    game.restart 
    end 
end 

您的模塊還沒有改變Player的行爲,因爲你沒有做任何事情來您的播放器。因此,讓我們擴展我們的播放器實例與SpecialPlayer

player.extend SpecialPlayer 
player.special? # true 
player.pause_game # pauses the game 
player.restart_game # restarts the game 

這樣做的好處是,在系統中的任何其他球員不必在乎誰是特殊的或他們是如何得到這樣:

other_player = Player.new 
other_player.special? # false 
other_player.pause_game # NoMethodError: undefined method `pause_game' for #<Player> 
other_player.restart_game # NoMethodError: undefined method `restart_game' for #<Player> 

這也確保了不只是任何球員都可以是特殊的。從非特殊玩家撥打#restart_game甚至都不會起作用,所以您不會在常規玩家做他們不應該做的事情時出現錯誤。

+0

我真的很喜歡你的解決方案,它是Ruby處理它的方式 – 2012-02-11 14:06:22

2

由於SpecialPlayer對象應該在每輪結束時替換一個Player對象,所以我認爲不要創建一個SpecialPlayer類來擴展Player。

我反而會向玩家添加一個標誌,將其標記爲特殊(布爾特殊),並根據該標誌我會知道他是否可以執行特殊功能。

+0

這是一個很好的處理方法,但我在考慮是否有另一種方式來處理它,因爲如果特殊播放器有大量的數據和方法可能會佔用大量內存資源? – 2012-02-10 19:01:18

+0

別擔心。我無法想象多餘數據所佔用的內存太多了。而方法所佔用的內存量是「固定開銷」;它不會隨着創建的對象實例的數量而增加。 – 2012-02-10 20:33:24

0

基本上你希望Player的行爲根據它是否特殊而有所不同。在這種類型的問題中,將變化的行爲封裝在接口(IHandling)中並讓原始類取決於此接口的實現是非常有用的。在你的情況下,你會讓Player委託不同的行爲爲SpecialHandlingNormalHandling。你的正常處理無能爲力。每輪之後,SpecialHandling對象可以連接到另一個Player

積分應存儲在Player類中,因爲這是常用功能。但是,假設使用SpecialHandling將積分乘以Player,則Player類將該代理委託給IHandling實例。

1

這聽起來像是裝飾者模式的工作。您可以使用與普通Player類相同的接口(IPlayer)創建SpecialPlayer類。 SpecialPlayer類還有一個player屬性(指向特殊玩家的指針)和一個assignPlayer方法,該方法在每一輪結束時被調用以將player屬性設置爲指向新特殊玩家的指針。從IPlayer繼承的SpecialPlayer類的所有方法應該從player屬性調用相應的方法。

+0

我使用紅寶石,所以沒有界面,因爲它是一種動態語言 – 2012-02-11 14:04:07

+0

我今天從我的課程講師那裏問了同樣的問題,他也指出了裝飾者。 – 2012-02-13 14:51:04