基本クラス BC と 2 つの派生クラス DC_A および DC_B を持つ次のクラス構造を想定してみましょう。さらに、タイプ BC のパラメーターを持つメソッド goo() を持つクラス XY と他のメソッドがあります
// base class
public class BC
{
public virtual void foo();
}
// derived class A
public class DC_A : BC
{
public override void foo() {}
}
// derived class B
public class DC_B : BC
{
public override void foo() {}
}
public class XY
{
public void goo(BC o)
{
// perfectly fine using polymorphism; no Ifs' no casting, OOP at its best ;-)
o.foo();
// but what to do here?
if ( (o as DC_A) != null )
{
doX(o as DC_A);
}
else if ((o as DC_B) != null)
{
doY(o as DC_B);
}
}
private void doX(DC_A o) {}
private void doY(DC_B o) {}
}
In 'ポリモーフィズムを使用して値オブジェクトを渡すのは悪い習慣ですか? ' Visitor パターンが提案されます。
If カスケードとキャストの問題は、抽象基本クラスに移動されます (排除されません)。
if を完全に回避するためのより良い解決策はありますか?
(この例では) 機能を doX/doY からクラス DC_A/DC_B に移動するオプションはありません。
あなたのアドバイスは大歓迎です。
編集:この質問の背景は、測定タイプ、テスト制限などのコレクション(私のDC_A、DC_Bクラス)を持つTestSpecのような異なるサブエンティティで構成される「テストルール」を管理するフォームを備えたC#/ WinFormsアプリケーションです。すべて EntityBase から派生 (=上記の BC) フォームは、サブエンティティが変更されたというイベントをコントローラーに送信します。単純化された PropertiesChanged(EntityBase o) コントローラーは、モデル クラスの対応するメソッド (上記のクラス XY のメソッド goo) を呼び出します。このメソッドは、変更されたサブ エンティティ テスト制限を保持するだけでなく、たとえば新しいテスト リミット リビジョン オブジェクト、テスト スペック リビジョンの増加など。
しかし、この特別なケースにより、ポリモーフィズムについてのより一般的な、または「哲学的」な質問に私は導かれました ;-)