[解決済み] C#: 戻り値のオーバーライド
2023-05-10 16:36:33
質問
C# で戻り値の型をオーバーライドする方法はありますか?もしあればどのように、なければなぜ、そして推奨される方法は何ですか?
私のケースは、抽象的なベースクラスとその子孫を持つインターフェースを持っているということです。私はこれをしたいと思います(実際にはそうではありませんが、例として!)。
public interface Animal
{
Poo Excrement { get; }
}
public class AnimalBase
{
public virtual Poo Excrement { get { return new Poo(); } }
}
public class Dog
{
// No override, just return normal poo like normal animal
}
public class Cat
{
public override RadioactivePoo Excrement { get { return new RadioActivePoo(); } }
}
RadioactivePoo
はもちろん
Poo
.
私がこれを望む理由は、"li" と "li "の間にある
Cat
オブジェクトを使う人が
Excrement
をキャストすることなく
Poo
を
RadioactivePoo
に変換し、例えば
Cat
の一部である可能性があります。
Animal
の一部であり、ユーザーは必ずしも放射性うんちを意識したり気にしたりしないかもしれません。ご理解いただけたでしょうか...
私が見る限り、コンパイラは少なくともこれを許可していません。ですから、それは不可能だと思います。しかし、これに対する解決策として何をお勧めしますか?
どのように解決するのですか?
この問題に対する解決策はすでにたくさんありますが、私は既存の解決策で抱えていた問題を解決する方法を思いついたと思います。
私は以下の理由で既存のソリューションのいくつかに満足していませんでした。
- Paolo Tedescoの最初の解答です。 Cat と Dog は共通のベースクラスを持っていません。
- Paolo Tedescoの2番目の解決策です。 少し複雑で読みにくいです。
- Daniel Daranas氏の解答です。 これは動作しますが、多くの不要なキャストとDebug.Assert()ステートメントでコードを混乱させるでしょう。
- hjb417の解決策です。 この解決策では、ロジックを基底クラスで保持することができません。この例ではロジックはかなり些細なものですが(コンストラクタを呼び出す)、実際の例ではそうではないでしょう。
私の解決策
この解決策は、ジェネリックとメソッド隠蔽の両方を使用することで、上記で述べたすべての問題を克服できるはずです。
public class Poo { }
public class RadioactivePoo : Poo { }
interface IAnimal
{
Poo Excrement { get; }
}
public class BaseAnimal<PooType> : IAnimal
where PooType : Poo, new()
{
Poo IAnimal.Excrement { get { return (Poo)this.Excrement; } }
public PooType Excrement
{
get { return new PooType(); }
}
}
public class Dog : BaseAnimal<Poo> { }
public class Cat : BaseAnimal<RadioactivePoo> { }
このソリューションでは、DogまたはCatで何かをオーバーライドする必要はありません。以下は使用例です。
Cat bruce = new Cat();
IAnimal bruceAsAnimal = bruce as IAnimal;
Console.WriteLine(bruce.Excrement.ToString());
Console.WriteLine(bruceAsAnimal.Excrement.ToString());
これは "RadioactivePoo" を2回出力し、多相性が崩れていないことを示します。
さらなる読み方
- 明示的なインターフェイスの実装
- 新しいモディファイア . この単純化されたソリューションでは使用しませんでしたが、より複雑なソリューションでは必要になるかもしれません。例えば、BaseAnimal のインターフェースを作成したい場合、 "PooType Excrement" のデクレレーションでそれを使用する必要があります。
-
out Generic Modifier (Covariance) (共分散)
. このソリューションでも使いませんでしたが、もしreturnのようなことをしたかったら
MyType<Poo>
をIAnimalから取得してMyType<PooType>
を返すのであれば、この2つの間でキャストを行えるようにするために使う必要があります。
関連
-
[解決済み】WebForms UnobtrusiveValidationModeは、jqueryのScriptResourceMappingを必要とする
-
[解決済み] [Entity Framework 4.1でエンティティに関連オブジェクトを追加する際に、エンティティオブジェクトをIEntityChangeTracker.の複数のインスタンスから参照できない。
-
[解決済み】ORA-01008: すべての変数がバインドされていません。これらはバインドされています。
-
[解決済み】C# - パスに不正な文字がある場合
-
[解決済み】WSACancelBlockingCallの例外について
-
[解決済み] C++のPOD型とは何ですか?
-
[解決済み] イールドリターン」の正しい使い方
-
[解決済み] JavaでequalsとhashCodeをオーバーライドする際に考慮すべき事項は?
-
[解決済み] なぜJavaは静的メソッドのオーバーライドを認めないのですか?
-
[解決済み] サブクラスでのフィールドやプロパティのオーバーライド
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
[解決済み】「未割り当てのローカル変数を使用」とはどういう意味ですか?
-
[解決済み] エンティティタイプ <type> は、現在のコンテキストのモデルの一部ではありません。
-
[解決済み】Moqを使用してメソッド呼び出しを検証する
-
[解決済み】値をNULLにすることはできません。パラメータ名:source
-
[解決済み】ファイルへの読み書きの際に共有違反のIOExceptionが発生する C#
-
[解決済み】Unityでゲームオブジェクトのすべての子をループスルーして破壊する方法?
-
[解決済み】Microsoft.Extensions.LoggingからILoggerを解決することができない
-
[解決済み】WebResource.axdとは何ですか?
-
[解決済み】名前 'ViewBag' が現在のコンテキストに存在しない - Visual Studio 2015
-
[解決済み】Nullableオブジェクトは値を持たなければならない?