2

オーバーライドできるメソッドを持つ基本クラスがあります。この基本クラスからクラスを継承する場合、メソッドに継承された型を返すようにするにはどうすればよいですか?

好き:

public class ClassA : BaseClass
{
    public override ClassA TestMethod(...)
    {
        // ...
    }   
}

基本クラスに手動で型を指定する必要がありますか?または、そのタイプを自動的に提供させることはできますか?

4

3 に答える 3

8

ジェネリック型を使用してそれを行うことができます。

public class BaseClass<T> where T : BaseClass<T> {
    public abstract T TestMethod(...);
}

public class ClassA : BaseClass<ClassA>
{
    public override ClassA TestMethod(...)
    {
        // ...
    }   
}

なぜあなたはそれが必要なのですか?より適切な答えにつながる可能性があります...

于 2013-01-08T15:26:18.453 に答える
7

必要な機能には名前があります。これはリターンタイプの共分散です。

C#でサポートされていない理由は次のとおりです。

インターフェイスを実装するときにC#がリターンタイプの継承を許可しない理由

他の答えはすべて、問題を解決するために不思議なことに繰り返されるテンプレートパターンのC#バージョンを使用することを示唆しています。私の意見では、パターンは解決するよりも多くの問題を引き起こします。詳細については、そのテーマに関する私の記事を参照してください。

http://blogs.msdn.com/b/ericlippert/archive/2011/02/03/curiouser-and-curiouser.aspx

この問題を解決するためのより良い方法は、次のパターンを使用することです。

abstract class Animal
{
    protected abstract Animal ProtectedGetMother();

    public Animal GetMother()
    {
      return this.ProtectedGetMother();
    }
}
class Cat : Animal
{
    protected override Animal ProtectedGetMother()
    {
      do the work particular to cats here
      make sure you return a Cat
    }
    public new Cat GetMother()
    {
      return (Cat)this.ProtectedGetMother();
    }
 }

問題は、異なる戻りタイプで仮想メソッドをオーバーライドできないことです。だからしないでください。戻り値のタイプが異なるまったく新しいメソッドを作成し、仮想メソッドをクラス階層の実装の詳細にします

Cat : Animal<Cat>このテクニックは、この「猫は猫の動物である」というナンセンスよりも約10億倍理解しやすいものです。

于 2013-01-08T16:10:09.170 に答える
2

これは一般的な方法で行うことができます。

public abstract class Base
{
    public abstract T AbstractTestMethod<T>() where T : Base;

    public virtual T VirtualTestMethod<T>() where T : Base, new()
    {
        return new T();
    }
}

public class ClassA : Base
{
    public override ClassA AbstractTestMethod<ClassA>()
    {
        return new ClassA();
    }

    public override ClassA VirtualTestMethod<ClassA>()
    {
        return new ClassA();
    }
}

仮想メソッドの使用は、抽象メソッドの使用ほど厳密ではありません。抽象的方法を使用すると、開発者に独自にメソッドを実装させることができます。仮想的な方法を使用すると、「私の制約を満たし、デフォルトの動作を自由に使用できる」などのように伝えることができます。

于 2013-01-08T15:29:52.233 に答える