6

わかりました、基本クラスから派生したさまざまなクラスがいくつかあります。この基本クラスは、一般的なメソッドを含む抽象です。

メソッドの 1 つはメソッドでありCopy、すべての派生クラスに存在する必要があるため、基本クラスに配置しました。derived typeしかし、私はそれがベースでもオブジェクトでもないものを返したいと思っています。

そのために得た解決策は、型パラメーターを使用することです。

abstract class CopyableClass<T>
{
    public abstract T Copy();
}

class DerivedClass : CopyableClass<DerivedClass>
{
    public override DerivedClass Copy()
    {
        //do what is needed for copy and return a new DerivedClass
    }
}

つまり、ここでの主な目的は

基本クラスの型パラメーターを削除し、引き続きメソッドが対応する派生型を返すようにします。


1 つの回避策。

これまでに私ができる最善のことは、以下のコメントの1つですが、それでもジェネリックパラメーターを使用しています

abstract class BaseClass
{
    //base methods not related to deriving type
}

interface ICopyable<T>
{
     T Copy();
}

class DerivedClass : BaseClass, ICopyable<DerivedClass>
{
    public DerivedClass Copy()
    {
        //do what is needed for copy and return a new DerivedClass
    }
}
4

4 に答える 4

5

あなたは本当にできません。基本クラスは、将来のすべての実装を認識できない可能性があります。ジェネリック抽象クラス(あなたがしたように)タイプまたはジェネリックCopyメソッドに頼る必要があります。

public abstract class CopyableClass
{
    public abstract T Copy<T>() where T : CopyableClass;
}

public class DerivedClass : CopyableClass
{
    public override T Copy<T>()
    {
        if(typeof(T) != typeof(DerivedClass))
            throw new ArgumentException();

        // return your copy
    }
}

または、基本クラスで型チェックを一般化する場合は、次のようにします。

public abstract class CopyableClass
{
    public T Copy<T>() where T : CopyableClass
    {
        if(GetType() != typeof(T))
            throw new ArgumentException();

        return (T) Copy();
    }

    protected abstract CopyableClass Copy();
}

public class DerivedClass : CopyableClass
{
    protected override CopyableClass Copy()
    {
        return // Your copy;
    }
}

2 番目のメソッドは、抽象化されたメソッドの戻り値をやみくもにキャストするため、派生クラスの実装に多くの信頼を置くことに注意してください。コンパイラは、派生型で CopyableClass を実装する別の型を返すことができますが、これは実行時エラーになります。すべての派生実装を完全に制御できる場合 (つまり、抽象クラスにも内部コンストラクターがある場合)、これは問題ではありません。

于 2013-07-02T17:53:38.970 に答える
0

これにより、この基本クラスを派生型にケース化して返すことができます。

public abstract class BaseClass<TDerived> : where TDerived: BaseClass<TDerived>
{
   public TDerived DoSomethingCommon(string param)
   {
      var derivedType = (TElement)this;
      //do something.
      return derivedType;
   }
}
于 2014-03-07T18:50:40.480 に答える
0

実際には、基本クラスにコピーを実装し、それを返す必要がありTます。これにより、型引数を指定して呼び出すと、その型が返されます。

public static T Copy<T>() where T : CopyableClass
{
    T retVal = new T();
    // do whatever copying is required
    return retVal;
}

それを呼ぶためにあなたはそうします。

DerivedClass d = Copy<DerivedClass>();

実際にコピーを行うコードは、ジェネリックにするのに少し手間がかかるかもしれませんが、Copy()派生型に対して機能する単一の実装があることを考えると、努力する価値があります。メソッドに属するロジックがわからないので、スタブしてみました。また、一般的にジェネリックをチェックすることをお勧めします。多くの場合、このような場合に最適なオプションです。実装を基本クラスに固有にする必要がある場合は、同じメソッド定義を保持しますが、抽象化し、基本クラスでオーバーライドします。

于 2013-07-02T17:53:43.190 に答える