2012-02-10 12 views
0

は、私は良いタイトルを選んだかどうかわかりませんが、私は、単純なカードベースのゲームを開発していますし、これは私のシナリオです:この継承方法は間違っていますか?

私が持っているプレーヤーと私はいくつかのオブジェクトをインスタンス化していると呼ばれるクラス(Playerに4と言う)。ゲームの各ラウンドで我々はプレーヤーの特別な種類があると言うことができますSpecialPlayerこれらの4つの選手の各ラウンドでは、SpecialPlayerすることができます。

SpecialPlayerはシンプルなプレイヤーであり、さらにいくつかのことを行うことができます。ゲームを一時停止/再起動することもできます。だから私はPlayerから継承してSpecialPlayerを作成し、そのクラスに2つのメソッドを追加しました。 問題は、私がSpecialPlayerをインスタンス化するときに、別のオブジェクトとそれらの4つのプレイヤーオブジェクトがあることです.Okですが、SpecialPlayerのプロパティを変更して、そのラウンドのSpecialPlayerだったPlayerオブジェクトの効果を確認できます。

たとえば、各プレイヤーはスコアポイントを獲得できます。私は、SpecialPlayerがポイントを獲得し、そのスコアとその効果をPlayerオブジェクトに変更したいのですか?

ここでの継承は間違っていますか? SpecialPlayerクラスのPlayerクラスを作成する必要がありますか?

答えが変わる可能性がある場合は、Rubyを使用しています。

答えて

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の方法です –

2

SpecialPlayerオブジェクトは各ラウンドの最後にPlayerオブジェクトを置き換える必要があるため、Playerを拡張するためにSpecialPlayerクラスを作成しない方が適切だと思います。

Playerに特別な(ブール値の特別な)マークを付けるフラグを追加して、特別な機能を実行できるかどうかを知ることができます。

+0

それは良い扱い方ですが、それを扱う別の方法があると思っていました。なぜなら、スペシャルプレイヤーの画像にはたくさんのデータとメソッドがあり、RAMに多くのリソースを占めているからです。 –

+0

それは心配しないでください。私は余分なデータによって奪取されたメモリがあまりにも多くなるとは想像もできません。メソッドによって取られるメモリの量は "固定オーバーヘッド"です。作成されるオブジェクトインスタンスの数が増えることはありません。 –

0

基本的には、Playerの動作が特殊かどうかによって異なります。この種の問題では、変化する動作をインタフェース(IHandling)にカプセル化し、元のクラスをこのインタフェースの実装に依存させることが有用です。あなたのケースでは、Playerがさまざまな振る舞いをSpecialHandlingまたはNormalHandlingのいずれかに委譲させるでしょう。あなたの通常の取り扱いは何もできません。各ラウンドの後、SpecialHandlingオブジェクトは別のPlayerにアタッチすることができます。

ポイントは共通の機能であるため、Playerクラスに保存する必要があります。しかし、Playerの場合、SpecialHandlingを使用してポイントを掛け合わせると仮定すると、PlayerクラスはこれをIHandlingインスタンスに委譲します。

1

これはデコレータパターンの仕事のようです。通常のPlayerクラスと同じインターフェイス(IPlayer)でSpecialPlayerクラスを作成できます。 SpecialPlayerクラスには、player属性(特別なPlayerへのポインタ)と、新しい特殊プレーヤーへのポインタにplayer属性を設定するために各ラウンドの最後に呼び出されるassignPlayerメソッドもあります。 IPlayerから継承されたSpecialPlayerクラスのすべてのメソッドは、player属性から対応するメソッドを呼び出す必要があります。

+0

私はRubyを使用しているので、インタフェースはありません。動的言語ですから –

+0

今日私のコース講師から同じ質問がありました。彼はデコレータも指していました。 –

関連する問題