質問

基本型でメソッドを宣言することとの違いは何ですか?virtual" そして、それを子型で使用してオーバーライドします。"override" キーワードを単に使用するのではなく、"new子型でマッチングメソッドを宣言するときに「キーワード?」

役に立ちましたか?

解決

" new"キーワードはオーバーライドせず、基本クラスのメソッドとは関係のない新しいメソッドを示します。

public class Foo
{
     public bool DoSomething() { return false; }
}

public class Bar : Foo
{
     public new bool DoSomething() { return true; }
}

public class Test
{
    public static void Main ()
    {
        Foo test = new Bar ();
        Console.WriteLine (test.DoSomething ());
    }
}

これはfalseを出力します。オーバーライドを使用した場合はtrueを出力します。

(Joseph Daigleから取得した基本コード)

したがって、実際のポリモーフィズムを行っている場合は、常にオーバーライドする必要があります。 " new"を使用する必要がある唯一の場所メソッドが基本クラスのバージョンに一切関連していない場合です。

他のヒント

私はいつも写真でこのようなことをより簡単に理解できます:

もう一度、joseph daigleのコードを取得します

public class Foo
{
     public /*virtual*/ bool DoSomething() { return false; }
}

public class Bar : Foo
{
     public /*override or new*/ bool DoSomething() { return true; }
}

次のようなコードを呼び出す場合:

Foo a = new Bar();
a.DoSomething();

注:重要なことは、オブジェクトが実際には Bar であることですが、タイプ Foo の変数に格納しています strong>(これはキャストに似ています)

クラスを宣言するときに virtual / override を使用したか、 new を使用したかに応じて、結果は次のようになります。

仮想/上書き説明画像

仮想メソッドと非仮想メソッドの動作の違いを理解するためのコードを次に示します。

class A
{
    public void foo()
    {
        Console.WriteLine("A::foo()");
    }
    public virtual void bar()
    {
        Console.WriteLine("A::bar()");
    }
}

class B : A
{
    public new void foo()
    {
        Console.WriteLine("B::foo()");
    }
    public override void bar()
    {
        Console.WriteLine("B::bar()");
    }
}

class Program
{
    static int Main(string[] args)
    {
        B b = new B();
        A a = b;
        a.foo(); // Prints A::foo
        b.foo(); // Prints B::foo
        a.bar(); // Prints B::bar
        b.bar(); // Prints B::bar
        return 0;
    }
}

new キーワードは、実際にはその特定のタイプにのみ存在する完全に新しいメンバーを作成します。

たとえば

public class Foo
{
     public bool DoSomething() { return false; }
}

public class Bar : Foo
{
     public new bool DoSomething() { return true; }
}

メソッドは両方のタイプに存在します。リフレクションを使用して、 Bar 型のメンバーを取得すると、実際にはまったく同じに見える DoSomething()という2つのメソッドが見つかります。 new を使用することで、基本クラスの実装を効果的に非表示にし、クラスが Bar から派生する場合(この例では)、 base.DoSomething( ) Foo ではなく Bar に移動します。

virtual / override は、2つのメソッドが関連しており、状況によっては最初の(仮想)メソッドを呼び出していると思われる場合に、2番目の(オーバーライドされた)メソッドを呼び出すことが実際に正しいことをコンパイラーに伝えます代わりにメソッド。これがポリモーフィズムの基礎です。

(new SubClass() as BaseClass).VirtualFoo()

サブクラスのオーバーライドされたVirtualFoo()メソッドを呼び出します。

new は、基本クラスのメソッドと同じ名前の派生クラスにメソッドを追加することをコンパイラーに伝えますが、それらは相互に関係がありません。

(new SubClass() as BaseClass).NewBar()

BaseClassのNewBar()メソッドを呼び出しますが、

(new SubClass()).NewBar()

SubClassのNewBar()メソッドを呼び出します。

技術的な詳細だけでなく、仮想/オーバーライドを使用すると、設計に関する多くのセマンティック情報が伝達されると思います。メソッドvirtualを宣言すると、実装クラスが独自のデフォルト以外の実装を提供することを期待していることを示します。同様に、基本クラスでこれを省略すると、すべての実装クラスでデフォルトのメソッドで十分であるという期待が宣言されます。同様に、抽象宣言を使用して、クラスの実装に独自の実装を強制することができます。繰り返しになりますが、これはプログラマーがコードがどのように使用されることを期待するかについて多くのことを伝えていると思います。基本クラスと実装クラスの両方を書いていて、新しいクラスを使用していることに気付いた場合は、親でメソッドを仮想化せず、具体的に意図を宣言するという決定を真剣に考え直します。

オーバーライドキーワードと新しいキーワードの違いは、前者はメソッドのオーバーライドを行い、後者はメソッドの非表示を行うことです。

詳細については、以下のリンクをご覧ください...

MSDN およびその他

  • new キーワードは非表示用です。 -実行時にメソッドを非表示にしていることを意味します。出力はベースクラスメソッドに基づきます。
  • オーバーライド用の
  • override 。 -は、基本クラスの参照を使用して派生クラスメソッドを呼び出すことを意味します。出力は、派生クラスメソッドに基づきます。

説明の私のバージョンは、プロパティを使用して違いを理解するのに役立ちます。

override は簡単ですよね?基になる型は親のオーバーライド

new はおそらく誤解を招くものです(私にとってはそうでした)。プロパティを使用すると理解しやすくなります。

public class Foo
{
    public bool GetSomething => false;
}

public class Bar : Foo
{
    public new bool GetSomething => true;
}

public static void Main(string[] args)
{
    Foo foo = new Bar();
    Console.WriteLine(foo.GetSomething);

    Bar bar = new Bar();
    Console.WriteLine(bar.GetSomething);
}

デバッガを使用すると、 Foo foo には 2 GetSomething プロパティがあり、実際には2つのバージョンのプロパティ > Foo Bar を使用し、どちらを使用するかを知るために、c#" picks"現在のタイプのプロパティ。

バーのバージョンを使用する場合は、オーバーライドを使用するか、代わりに Foo foo を使用します。

GetSomething の完全に新しい動作が必要なため、

バーバーには 1 しかありません。

メソッドに何もマークしないことは、次のことを意味します。ランタイム型 (静的バインディング) ではなく、オブジェクトのコンパイル型を使用してこのメ​​ソッドをバインドします。

メソッドをマークする virtual 手段:コンパイル時タイプ (動的バインディング) ではなく、オブジェクトの実行時タイプを使用してこのメ​​ソッドをバインドします。

基本クラスのマーク付け virtual を使用したメソッド override 派生クラスでは次のことを意味します。これは、オブジェクトのランタイム型 (動的バインディング) を使用してバインドされるメソッドです。

基本クラスのマーク付け virtual を使用したメソッド new 派生クラスでは次のことを意味します。これは新しいメソッドであり、基本クラス内の同じ名前のメソッドとは関係がなく、オブジェクトのコンパイル時の型 (静的バインディング) を使用してバインドされる必要があります。

基本クラスをマークしない virtual 派生クラスのメソッドは次のことを意味します。このメソッドは次のようにマークされています new (静的バインディング)。

メソッドのマーク付け abstract 手段:このメソッドは仮想メソッドですが、本体は宣言しません。また、そのクラスも抽象 (動的バインディング) です。

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top