0

抽象クラスに基づいてクラスを作成し、基本クラスに含まれる関数を、クラスによって渡される型である "T" の戻り値の型を持つ別の関数で上書きしようとしています。

例えば:

public abstract class DayInfo
{
    public virtual void GetInfo()
    {
        throw new NotImplementedException();
    }
}

public class DayInfo<T> : DayInfo
{
    private T info;
    public DayInfo(T data)
    {
        info = data;
    }

    public T GetInfo() // << This
    {
        return info;
    }
}

例:

1

DayInfo info = new DayInfo<String>("Blah");
String stuff = info.GetInfo();

2

DayInfo info = new DayInfo<int>(25);
int stuff = info.GetInfo();

これを達成する方法はありますか?

編集1:型を定義せずにジェネリック型として使用できるようにしたかったため、基本クラスでクラス渡し型を使用しなかったことを正確に忘れていました。

例えば:

public SortedDictionary<int, DayInfo> Data = new SortedDictionary<int, DayInfo>();

編集2:

また、基本クラスの仮想関数のポイントは、GetInfo() 関数がアクセスされたがオーバーライドされていない場合に、子クラスが例外をスローするようにすることです。

4

6 に答える 6

1

これがあなたの目標を達成する方法です:

public abstract class DayInfoA<T>
{
    public virtual T GetInfo()
    {
        .......
    }
}

public class DayInfoB<T> : DayInfoA<T>
{
    private T info;
    public DayInfoB(T data)
    {
        info = data;
    }

    public override T GetInfo() // << This
    {
      .........
    }
}

次のように使用します。

        DayInfoB<int> info = new DayInfoB<int>(25);
        int stuff = info.GetInfo();
于 2013-05-10T22:56:38.447 に答える
0

いいえ、あなたがそれを望んでいるようには見えません(基本クラスの宣言を変更したくない、または変更できないと仮定します)。関数がポリモーフィック呼び出しに解決されるためには、同じシグネチャと戻り値の型が必要です。それ以外の場合は、関数をポリモーフィックに解決しません。関数の基本クラス バージョンを呼び出すだけです。これは、呼び出していることがわかっているためです (インスタンスを割り当てた変数は基本クラス型です)。

あなたはこれを行うことができますが、それはかなり醜いです:

        DayInfo info = new DayInfo<String>("Blah");
        String stuff = ((DayInfo<string>)info).GetInfo();
于 2013-05-10T23:00:38.757 に答える
0

いいえ、関数は異なる関数シグネチャと一致しないためです。

あなたができることは、次のように定義することです:

public abstract class DayInfo
{
    public virtual object GetInfo()
    {
        throw new NotImplementedException();
    }
}

そして、次のような派生クラスで:

public object GetInfo() // << This
{
    return info;
}

次に、それらは両方とも同じ署名を持ち、ポリモーフィズムが一致します。ただし、反対側ではキャストが必要になります。

DayInfo info = new DayInfo<int>(25);
int stuff = (int)info.GetInfo();

編集:余談ですが、それ以上のものがない限り、それをインターフェースにするか、GetInfo本当に何もしない場合はGetInfo純粋に抽象化します。

public abstract object GetInfo();
于 2013-05-10T23:04:54.647 に答える
0

これは、NVI パターンで生成できます。

public abstract class DayInfo
{
  protected virtual void GetInfoCore() {
    throw new NotImplementedException();
  }

  // or
  // protected abstract void GetInfoCore();

  public void GetInfo() {
    GetInfoCore();
  }
}

public class DayInfo<T> : DayInfo
{
  private T info;

  public DayInfo(T data) {
    info = data;
  }

  public new T GetInfo() { // << This
    return info;
  }

  protected override void GetInfoCore() {
    GetInfo();
  }
}
于 2013-05-10T23:13:37.743 に答える
0

基本クラスの代わりに、または基本クラスに加えて、共変インターフェイスを作成できます。

void Main()
{
    IDayInfo dayInfo = new DayInfo<string>("hi!");
    object info = dayInfo.GetInfo(); //info == "hi!"
}
public interface IDayInfo
{
    object GetInfo();
}
public interface IDayInfo<out T> : IDayInfo
{
    new T GetInfo();
}

public class DayInfo<T> : IDayInfo<T>
{
    private T info;
    public DayInfo(T data)
    {
        info = data;
    }

    public T GetInfo()
    {
        return info;
    }
    object IDayInfo.GetInfo()
    {
        return this.GetInfo();
    }
}

(共分散/反分散とは何かについては、ジェネリック インターフェイスの分散を参照してください)

object info(の 2 行目Main) は、この例でキャストせずに得られるのと同じくらい正確であることに注意してください。DayInfo<string>オブジェクトを変数/フィールドに格納するIDayInfo<object>と、私が行ったように (そして辞書でやりたいように)、強い型付けはstringある意味で忘れられ、キャストなしでは復元できなくなります。

更新:IDayInfoインターフェイスを追加しました。

于 2013-05-10T23:15:36.603 に答える