2013-01-10 4 views
5

私はあなたの助けが必要です。 RPGゲームで能力を出す前に、さまざまな条件をチェックできるスクリプトを手配しています。C#、ユニティ - 複数の異なるオブジェクトを取る単一の機能

これらの能力はすべて、抽象クラスを親とする別の抽象クラス(能力、癒し能力、DOT能力)から派生した個々のクラス(ファイアボール、ヒール、ポイズン)です。

ひとつひとつの能力処理するために、複数の機能を作成しないようにするために:私は能力のすべてのタイプを取ることができ、単一の関数呼び出しを作成しようとしています

void condition(Fireball f){//test}; 
void condition(Heal f){//test}; 
void condition(Poison f){//test}; 

を。

void condition(Ability f){//test} 

これまでのところ、Fireballオブジェクトを作成して関数に渡しました。ここから

Fireball _fire = new FireBall(); 
condition(_fire); 

void condition(Ability f){//test} 

私は能力クラスで初期化し、すべてのパブリック変数にアクセスすることができますが、私は、派生クラス(遠距離能力、ヒーリング能力、DOT能力)で初期化パブリック変数にアクセスすることはできません。

私は何かを忘れているのですか、それとも間違った視点でこれを見ていますか? (私は継承クラスと抽象クラスを利用するのには大したことはありません)

+0

古典的なOOPの多型/継承問題:カプセル化を維持し、快適性を利用するソリューションを考えるのは難しいことです。 +1。 – dreamzor

+0

これはObjective Cとは何が関係していますか? –

+0

申し訳ありませんが、私は間違ってタグ付けしたと思います。 –

答えて

8

条件関数の詳細については、2つの選択肢があります。

一つ、あなたは

if (f.GetType() == typeof(FireBall)) 
{ 
    fireBall = (FireBall)f; 
    fireBall.FireTheFireBall(); 
} 
else if (f.GetType() == typeof(Heal)) 
... 

ような何かを行うことができますか、あなたの能力は、すべての派生クラスがオーバーロードするのに必要な抽象Activateメソッド、持つことができます。そして、働く任意のものを

class Fireball 
{ 
    public override void Activate() 
    { 
     //do fireball specific things 
     this.FireTheFireBall(); 
    } 

    public void FireTheFireBall() {...}  
} 

class Heal 
{ 
    public override void Activate() 
    { 
     //do healing specific things 
     this.ApplyTheBandage(); 
    } 
    ... 
} 

abstract class Ability 
{ 
    public abstract void Activate(); 
} 

void condition(Ability f){ 
    f.Activate(); //runs the version of Activate of the derived class 
} 

を能力はsomeAbility.Activate()を呼び出すことができ、派生クラスによって提供される実装が実行されます。

あなたはまた、抽象クラスのような種類のインターフェイスで勉強する必要があります。インターフェースのメリットは複数のものを実装できることですが、1つの基本抽象クラスから継承することに限られています。ターンとプルの機能を持つIKnobインターフェイスについて考えてみましょう。 IKnob、Doorクラス、Turnを実装し、トラップをアクティブにするTrappedDoorクラスを実装するDrawerクラスがあります。プレーヤーはので、もし何かがインタフェースを持っているかどうかを確認する方法は、あります

void Open(IKnob knob) 
{ 
    knob.Turn(); 
    knob.Pull(); 
} 

class TrappedDoor:IKnob,IMaterial,ISomethingElse,IHaveTheseOtherCapabilitiesAsWell 
{ 
    private bool TrapAlreadySprung{get;set;} 
    //more complex properties would allow traps to be attached either to the knob, or the door, such that in one case turning the knob activates the trap, and in the other, Pull activates the trap 
    public Turn() { 
    if(! TrapAlreadySprung) 
    { 
     MessageBox("You hit your head, now you're dead"); 
    } 
    } 
} 

ドアまで歩いて、それの使用ボタンをヒット、そしてあなたは、open関数にオブジェクトを渡し、オープン(IKnobノブ)プレイヤーによってはアイテムまで歩いて話をしようとすると、オブジェクトにICanTalkインターフェイスがあるかどうかを確認できます。オブジェクトが返されると、object.GetReply( "Hello")が呼び出されます。あなたが望むならば、ドアと岩を話すことができます。 ICanTalkインターフェイスメソッドを使って作業する/応答を表示するなど、ICanTalkを実装することができ、それぞれがどのように応答するかを決めることができます。この概念は「懸念の分離」として知られ、より再利用可能なコードを作成するのに役立ちます。

重要なことは、そのインターフェイスでしか動作しないコード、アルゴリズム、関数などを書くことができることです。そのコードをインターフェイスで使用すると、そのインターフェイスを使用できますどのクラスでも使用でき、そのクラスは既存のコードを活用できます。

I.e. condition関数は、IAbilityインターフェースを取り込んだら、そのコードが動作すれば、IAbilityを実装するクラスを作成して条件関数に渡すことができます。条件関数は、それが想定していたことを実行することを担当しており、IAbilityを実装しているクラスは、実装したメソッドの中でそれに特有のものを処理します。

もちろん、抽象クラスまたはインターフェイスを実装するクラスは、必要なメソッドを実装する必要があるため、コードを複製しているように感じることがあります。たとえば、TrappedDoorとDoorのような類似クラスがある場合、TrappedDoorは、トラップが設定されていない/既に張られている場合、通常のDoorのように動作します。だから、あなたはこのケースではDoorから継承するか、私的なDoorプロパティ(「合成」と呼ばれます)を持つことができます。トラップがすでに起動されている場合は、基本DoorクラスまたはプライベートDoorプロパティを呼び出して、トラップがアクティブでない場合に通常のドアのデフォルト動作を再利用できるように.Turnを呼び出すことができます。個人

Test if object implements interface

Iはほとんどインターフェースと組成、代わりの継承を使用します。その継承はひどいものですが、継承階層はすぐに非常に複雑になります。

+0

ありがとうございました。私は2番目の提案がどのように機能するかはわかりませんが、実際には最初の提案がうまくいくと思います。 私はできるだけ早くそれを調べ、私は戻って報告します:) –

+0

@Marc 2番目の例を展開するように更新しました。 – AaronLS

+1

2番目の例は、私が疑うより賢明なアイデアのように見えます。:) –

関連する問題