2

抽象クラスで正確な名前で仮想メソッドを初期化したい。

そして、継承者のオーバーライド メソッドであるクラスでは、オーバーライドできます。

  • 基本メソッドの戻り値の型
  • メソッドの引数

お見せするために、私が本当にやりたいことは次のようなものです:

abstract class A
{
    public virtual void Func1() { }
}

class B : A
{
    override string Func1(int a, int b)
    {
         return (a + b).ToString();
    }
}

newC# では、基本クラスと同様に戻り値の型/引数を使用する必要があることはわかっていますが、この状況ではキーワードを使用したヒントがいくつかあるのではないでしょうか?

4

5 に答える 5

4

override正確な名前と引数のみを使用できます。好きなようにできnewますが、それはオーバーライドではありません。完全に一致した場合に非表示にするだけです。

あなたの状況では、考えられるすべての組み合わせのオーバーロードを作成するか、必要な引数を含むことができる単一の型を取る単一の基本抽象メソッドを作成する必要があると思います。

例:

public abstract void Func1( MyArgumentsType input );

現在、派生クラスはメソッドをオーバーライドする必要がありますが、より多くのシナリオを処理できる堅牢な引数のセットをメソッドに渡すことができます。

ここではポリモーフィズムが有利に働きます。派生した引数の型を状況固有のプロパティを持つメソッドに渡すことができるからです。もちろん、これには実装メソッドがより派生した引数の型を理解する必要があります。

于 2013-01-07T18:18:35.867 に答える
3

あなたはこれを行うことはできません。メソッドをオーバーライドするには、パラメーターと戻り値の型を含むまったく同じ署名が必要です。異なるパラメーターと戻り値の型でメソッドをオーバーライドするようにコンパイラーに指示する方法はありません。

ポリモーフィックな動作が必要な場合は、互換性のあるシグネチャが必要です。そうしないと、コンパイラーは、必要なメソッドがポリモーフィックに見つかることを保証できません。

シグネチャをポリモーフィックとして扱う考えられる方法はありませvoid Func1()string Func1(int a, int b)。内部でパス ラムダのパラメーターを使用してそれらを一般化できoutますが、とにかく - ポリモーフィックな動作を利用するには、それらを 1 つの共通のシグネチャにする必要があります。

于 2013-01-07T18:18:45.830 に答える
3

メソッドのオーバーライドとは、継承されたメンバーの署名ではなく、その仮想実装を変更することを意味します。あなたが指摘したように、キーワードは同じ名前のメンバーの基本クラスの実装を隠します。ただし、これはオプションにすぎません。基本クラス メンバーと同じ名前を持つ派生クラス メンバーで new キーワードを使用するこの利点を見てください。new

于 2013-01-07T18:19:39.037 に答える
3

さまざまなタイプ (や など)ToStringに対してさまざまなフレーバーを持つメソッドに似た動作を実現したいようです。.ToString()float.ToString("c")

この場合、 の異なる実装は の実装でToStringはなくObject.ToString、引数に基づいて適切に解決される派生オブジェクトの通常の追加メソッドです。すべての派生クラスは、最終的に 1 つの仮想ToStringメソッド (基本クラスから派生し、現在のクラスに実装される可能性がある) と、オプションで、仮想ではない他の同様の名前のメソッドを持ちます。

C# では、新しい方の結果型が関数の解決時間に考慮されることに注意してください。そのため、同じ名前と同じ引数を持つ 2 つの関数を実際に持つことはできず、1 つが「正しく」選択されることを期待できません。両方が同時に表示されると、コンパイル時エラーが発生します。newメソッドの前のキーワードは、そのクラス (および派生したもの) に対してそのメソッドのみを表示し、同じシグネチャを持つ基本クラスのメソッドを非表示にします。残念ながら、これを行うと、派生クラスを保持する基本クラスの変数を使用してこのメ​​ソッドを呼び出すときに、多くの混乱が保証されます。基本クラスの仮想変数は、隠蔽するためのあらゆる努力にもかかわらず呼び出されます。

于 2013-01-07T18:26:50.030 に答える
1

考えてみてください...どのように機能しますか?次のように、静的型が であるAが動的型がである参照があるBとします。

foo(B b) { bar(b); }
bar(A a) { 
}

オーバーライドの背後にある考え方は、スーパー/ベースでメソッドを呼び出すと、オーバーライドされた実装に解決されるということです。barそのロジックにより、 inで呼び出すことができ、 inでa.Func1()メソッドを呼び出す必要がありますB

a.Func1(???)

しかし、ここではパラメーターが欠落しているため、それは不可能です。

パラメーターの反変性と戻り型の共分散の概念があります。これはSOの興味深い回答であり、興味深い読み物になるはずのEric Lippertによる投稿へのリンクがあります。

于 2013-01-07T18:35:24.003 に答える