戻り値の型がサブクラスによって異なる必要がある場合は、このメソッドを基底クラスに持たない方がよいでしょう。
基本型の背後にあるアイデアは、すべてのサブクラスを統一的に処理できるようにすることです。 1つは書くことができるはずです
Command cmd = ... // One of subclasses
<some-type> val = cmd.GetValue();
<some-type>
を実際のタイプに置き換えてください。しかし、あなたのケースでは、とstring
にはobject
以外の共通の基底型はありません。したがって、異なる戻り型を持つことは無意味になります。
あなたはこのように、一般的なようGetValue
を実装できます。
abstract class Command {
abstract T GetValue<T>();
...
}
それは、基本クラスでGetValue
を持つことの目的を倒すことになる、GetValue
の型パラメータとして所望のタイプを渡すために、発信者を必要とします。
可能な修正:発信者が型を知っているから離れて滞在することができます訪問者です一つのアプローチ - このようなCommand
「プッシュ」の呼び出し元に値、することができますインターフェイス作る:今
IValueGetter {
void SetInt(int v);
void SetString(string v);
}
abstract class Command {
abstract void GetValue(IValueGetter g);
}
class TalkCommand {
override void GetValue(IValueGetter g) {
g.SetString("hello");
}
}
class BuyCommand {
override void GetValue(IValueGetter g) {
g.SetInt(123);
}
}
を呼び出し元はの種類を知らずにCommand
と対話できます。 int
を生成するコマンドはSetInt
をコールし、string
を生成するコマンドはSetString
をコールします。
逆の方向に進むことができます。 'Command'は*主実装*であり、 'Command'ジェネリック型パラメータなしは' Command 'の派生クラスです。そうすれば、コマンドの一般的な使用は、オブジェクトから 'T 'への不必要なキャストを避けることができます –
@MatíasFidemraizer私は同意しません。 'コマンド'をタイプ( 'T')を知らずに使用する必要があるとき、' Command 'を作成することはできませんが、' Command'から継承しているため、その中で定義されているすべての関数を使用できます。 (IEnumerable :IEnumerable'など) –
これはプロジェクトにも依存するかもしれません...おそらく私は間違っていますが、共分散/逆ジェネリックではこれらの能力があるので、ジェネリックスが時間の無駄で複雑すぎると思っている場合を除き、クラス継承を使う代わりに解決できるものよりも多くの問題がある(私はあなたについて話していない、私はジェネリックプログラミングが大好きです!) –