17

いくつかのメソッドを含むインターフェースがあります。

interface IMyInterface
{
    //...
    void OnItemClicked()
    //...
}

そして実装

class MyClass : IMyInterface
{
    //Other methods
    public void OnItemClicked(){ /*...*/ } 
}

MyClassここで、を除いてのように動作するクラスがOnItemClicked()必要です。このメソッドにいくつかの変更を加えたいと思います。

オーバーライドを継承しようと思ったのですが、実装ではないため、( MyClasspublic virtualvoid OnItemClicked()...など)を変更したくありません。

IMyInterfaceOnItemClicked()はMyClassの変更する唯一の部分であるため、再度実装する必要はありません。

他に方法はありますか?

4

4 に答える 4

18

インターフェイスを実装しているので、ポリモーフィズムはおそらく維持したいものです。基本クラスを仮想で変更せずにメソッドをオーバーライドすることは不可能であるため、Tigranが書いたように仮想ではなくnewを使用する必要があります。

これは、この種のコードを記述しているが、メソッドの基本バージョンのみが実行されることを意味します。

List<MyClass> aList = new List<MyClass>();
aList.Add(new MyClass());
aList.Add(new MyNewClass());
foreach (MyClass anItem in aList)
    anItem.OnItemClicked();

適切なコードを実行するには、次のような醜いコードを書く必要があります。

List<MyClass> aList = new List<MyClass>();
aList.Add(new MyClass());
aList.Add(new MyNewClass());
foreach (MyClass anItem in aList)
{
    MyNewClass castItem = anItem as MyNewClass;
    if (castItem != null)
        castItem.OnItemClicked();
    else
        anItem.OnItemClicked();
}

とにかく、クラスがIMyInterfaceとして宣言された変数に割り当てられたときに、クラスに正しいメソッドを実行させる方法があります。実行する方法は、オーバーライドするインターフェイスの部分(この場合はOnItemClickedメソッド)を明示的に実装することです。コードは次のとおりです。

public class MyNewClass : MyClass, IMyInterface // you MUST explicitly say that your class implements the interface, even if it's derived from MyClass
{
    public new void OnItemClicked() //NEW keyword here you have the overridden stuff
    { 
        /*...*/ 
    } 

    void IMyInterface.OnItemClicked() // No need for public here (all interfaces's methods must be public)
    { 
        this.OnItemClicked(); 
    } 
}

この上:

 MyClass cl = new MyNewClass(); 
 cl.OnItemClicked();

基本メソッドを実行します

 MyNewClass cl = new MyNewClass(); 
 cl.OnItemClicked();

派生クラスのメソッドを実行します

 IMyInterface cl = new MyNewClass(); 
 cl.OnItemClicked();

派生クラスのメソッドを実行し、実行時にバインドされます。これは、私の最初の例のコードを次のように記述して、適切なメソッドを実行できることを意味します。

List<IMyInterface> aList = new List<IMyInterface>();
aList.Add(new MyClass());
aList.Add(new MyNewClass());
foreach (IMyInterface anItem in aList)
    anItem.OnItemClicked();
于 2012-09-07T10:08:20.463 に答える
5

あなたはから派生することができます MyClass

public class MyNewClass : MyClass
{
    public new void OnItemClicked(){ /*...*/ } //NEW keyword
}

唯一のことは、この方法ではポリモーフィズムをサポートしないことに注意してください。

より明確にするために:

     MyClass cl = new MyNewClass(); 
     cl. MyMethod();

これは、実際のオブジェクト タイプがMyClassであっても、メソッドを呼び出します。必要なものを呼び出せるようにするには、明示的に型を定​​義する必要がありますMyNewType

     MyNewClass cl = new MyNewClass(); 
     cl. MyMethod(); //WILL CALL METHOD WE WANT
于 2012-09-07T09:05:55.350 に答える
3

最も簡単な方法は、「has-a」を使用して「is-a」を模倣する新しいクラスを作成することです。

public interface IMyInterface
{
    void OnItemClicked();
    void OnItemHover();
    void OnItemDoubleClicked();
}

public class MyNewClass : IMyInterface
{
    private IMyInterface _target;

    public MyNewClass(IMyInterface target)
    {
        _target = target;
    }

    public void OnItemClicked()
    {
        // custom functionality
    }

    public void OnItemHover()
    {
        _target.OnItemHover();
    }

    public void OnItemDoubleClicked()
    {
        _target.OnItemDoubleClicked();
    }
}
于 2012-09-07T09:11:55.653 に答える
1

パターンブリッジを使用http://en.wikipedia.org/wiki/Bridge_pattern

于 2012-09-07T09:06:52.793 に答える