47

staticメソッドは暗黙的finalであるため、オーバーライドできないと言われました。本当?

  1. 誰かが静的メソッドをオーバーライドするより良い例を挙げてもらえますか?

  2. 静的メソッドが単なるクラス メソッドである場合、それらを持つことの実際の用途は何ですか?

4

3 に答える 3

42

(1) 静的メソッドはオーバーライドできませんが、「new」キーワードを使用して非表示にすることができます。ほとんどの場合、メソッドをオーバーライドするということは、基本型を参照し、派生メソッドを呼び出したいということです。static は型の一部であり、意味をなさない vtable ルックアップの対象にならないためです。

例: statics はできません:

public class Foo { 
    public virtual void Bar() { ... }
}
public class Bar : Foo {
    public override void Bar() { ... }
}

// use:
Foo foo = new Bar(); // make an instance
foo.Bar(); // calls Bar::Bar

静的はインスタンスでは機能しないため、常に Foo.Bar または Bar.Bar を明示的に指定します。したがって、オーバーライドはここでは意味がありません (コードで表現してみてください...)。

(2) 静的メソッドにはさまざまな使用法があります。たとえば、型の単一のインスタンスを取得するために Singleton パターンで使用されています。もう 1 つの例は、プログラムのメイン アクセス ポイントである「static void Main」です。

基本的に、使用する前にオブジェクトインスタンスを作成したくない、または作成できない場合はいつでもそれらを使用します。たとえば、静的メソッドがオブジェクトを作成するとき。

[アップデート]

簡単な非表示の例:

public class StaticTest
{
    public static void Foo() { Console.WriteLine("Foo 1"); }
    public static void Bar() { Console.WriteLine("Bar 1"); }
}

public class StaticTest2 : StaticTest
{
    public new static void Foo() { Console.WriteLine("Foo 2"); }
    public static void Some() { Foo(); Bar(); } // Will print Foo 2, Bar 1
}

public class TestStatic
{
    static void Main(string[] args)
    {
        StaticTest2.Foo();
        StaticTest2.Some();
        StaticTest.Foo();
        Console.ReadLine();
    }
}

staticクラスを作成すると、これを行うことができないことに注意してください。静的クラスは から派生する必要がありますobject

これと継承の主な違いは、静的を使用する場合に呼び出すメソッドをコンパイラがコンパイル時に決定できることです。オブジェクトのインスタンスがある場合は、実行時にこれを行う必要があります (vtable ルックアップと呼ばれます)。

于 2013-02-12T08:30:10.560 に答える
7

さて、静的メソッドをオーバーライドすることはできません。クラスのインスタンスに関連していないため、静的メソッドを仮想にすることはできません。

派生クラスの「オーバーライドされた」メソッドは、実際には新しいメソッドであり、基本クラスで定義されたものとは無関係です (したがって、 new キーワード)。

これは理解しておくべき重要なことです: 型が他の型から継承する場合、それらは共通の契約を満たしますが、静的型は (純粋な OOP の観点から) どの契約にも拘束されません。この言語には、2 つの静的型を「継承」コントラクトで結び付ける技術的な方法はありません。2 つの異なる場所で Log メソッドを「オーバーライド」する場合。

静的メソッドをオーバーライドすることを考えると、実際には意味がありません。仮想ディスパッチを行うには、チェックするオブジェクトの実際のインスタンスが必要です。

静的メソッドもインターフェイスを実装できません。このクラスが IRolesService インターフェイスを実装している場合、メソッドはまったく静的であってはならないと主張します。インスタンス メソッドを用意した方が良い設計なので、準備ができたら MockRoleService を実際のサービスと交換できます。

于 2013-02-12T08:27:08.487 に答える
5

静的メソッドをオーバーライドしません。あなたはそれを隠します。詳細については、この回答を参照してください。

静的メソッドを使用するいくつかの理由:

  1. これらはインスタンスメソッドよりも少し高速です。これをバックアップするためのパフォーマンス数値を示すこのmsdnの記事も参照してください(インライン静的呼び出し平均0.2 ns、静的呼び出し平均6.1 ns、インラインインスタンス呼び出し平均1.1 ns、インスタンス呼び出し平均6.8 ns)
  2. 書き出すのに冗長性が少ない-クラスに到達するためにクラスをインスタンス化する必要はありません(インスタンス化もパフォーマンスに影響を与える可能性があります)
于 2013-02-12T08:24:31.910 に答える