基本型 "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
型の変数に格納していることです(これはキャストに似ています)
クラスを宣言するときに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()
のメソッド呼び出しはBar
ではなくFoo
になります。
virtual/overrideは、2つのメソッドが関連しており、状況によっては最初の(仮想)メソッドを呼び出していると思われる場合に、代わりに2番目の(オーバーライドされた)メソッドを呼び出すのが正しいことをコンパイラーに伝えます。これがポリモーフィズムの基盤です。
(new SubClass() as BaseClass).VirtualFoo()
SubClassのオーバーライドされたVirtualFoo()メソッドを呼び出します。
newは、基本クラスのメソッドと同じ名前の派生クラスにメソッドを追加することをコンパイラーに伝えますが、それらは互いに関係がありません。
(new SubClass() as BaseClass).NewBar()
BaseClassのNewBar()メソッドを呼び出しますが、
(new SubClass()).NewBar()
SubClassのNewBar()メソッドを呼び出します。
技術的な詳細だけでなく、仮想/オーバーライドを使用すると、設計に関する多くのセマンティック情報が伝達されると思います。メソッドvirtualを宣言するとき、実装クラスが独自のデフォルト以外の実装を提供することを期待することを示します。同様に、基本クラスでこれを省略すると、すべての実装クラスでデフォルトのメソッドで十分であるという期待が宣言されます。同様に、抽象宣言を使用して、クラスの実装に独自の実装を強制することができます。繰り返しになりますが、これはプログラマーがコードがどのように使用されることを期待するかについて多くを伝えていると思います。基本クラスと実装クラスの両方を書いていて、新しいクラスを使用していることに気付いた場合、親でメソッドを仮想化せず、具体的に意図を宣言するという決定を真剣に考え直します。
Overrideキーワードとnewキーワードの違いは、前者がメソッドのオーバーライドを行い、後者がメソッドの非表示を行うことです。
詳細については、以下のリンクをご覧ください...
[〜#〜] msdn [〜#〜] および その他
new
キーワードは非表示用です。 -実行時にメソッドを非表示にしていることを意味します。出力はベースクラスメソッドに基づきます。override
をオーバーライドします。 -は、基本クラスの参照を使用して派生クラスメソッドを呼び出すことを意味します。出力は、派生クラスメソッドに基づきます。説明の私のバージョンは、違いを理解するためにpropertiesを使用することから来ています。
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
には2GetSomething
プロパティがあります。実際には、Foo
とBar
の2つのバージョンのプロパティがあり、どちらを使用するかを知るためです。 、c#は現在の型のプロパティを「選択」します。
バーのバージョンを使用する場合は、オーバーライドまたはFoo foo
代わりに。
Bar bar
には1のみがあり、完全に必要ですnewGetSomething
の動作。
メソッドに何もマークを付けないということは、実行時型ではなくオブジェクトのコンパイル型を使用してこのメソッドをバインドします(静的バインディング)。
メソッドをvirtual
でマークすると、次のことを意味します。コンパイル時の型ではなく、オブジェクトのランタイム型を使用してこのメソッドをバインドします(動的バインディング)。
派生クラスでvirtual
を使用して基本クラスoverride
メソッドをマークすることは、これがオブジェクトのランタイムタイプを使用してバインドされるメソッドであることを意味します(動的バインディング)。
派生クラスでvirtual
を使用して基本クラスnew
メソッドをマークすることは、これが新しいメソッドであり、基本クラスの同じ名前のメソッドとは関係がなく、次を使用してバインドする必要があることを意味します。オブジェクトのコンパイル時タイプ(静的バインディング)。
派生クラスで基本クラスvirtual
メソッドをマークしないということは、このメソッドがnew
(静的バインディング)としてマークされていることを意味します。
メソッドのマークabstract
は、このメソッドが仮想であるが、そのボディを宣言せず、そのクラスも抽象(動的バインディング)であることを意味します。