C#では、用語shadowingはどういう意味ですか? このリンク を読みましたが、完全には理解していません。
シャドウイングは、基本クラスのメソッドを隠します。リンクした質問の例を使用して:
class A
{
public int Foo(){ return 5;}
public virtual int Bar(){return 5;}
}
class B : A
{
public new int Foo() { return 1;}
public override int Bar() {return 1;}
}
クラスB
は、仮想メソッドBar
をオーバーライドします。 Ithides(シャドウ)非仮想メソッドFoo
。オーバーライドはoverrideキーワードを使用します。シャドウイングはnewキーワードで行われます。
上記のコードで、クラスFoo
でB
メソッドを定義するときにnewキーワードを使用しなかった場合、次のコンパイラ警告が表示されます。
'test.B.Foo()' hides inherited member 'test.A.Foo()'. Use the new keyword if hiding was intended.
仮想メソッドを実装する基本クラスがあるとします:
_public class A
{
public virtual void M() { Console.WriteLine("In A.M()."); }
}
_
メソッドMも定義する派生クラスもあります。
_public class B : A
{
// could be either "new" or "override", "new" is default
public void M() { Console.WriteLine("In B.M()."); }
}
_
ここで、次のようなプログラムを作成するとします。
_A alpha = new B(); // it's really a B but I cast it to an A
alpha.M();
_
実装方法には2つの異なる選択肢があります。デフォルトの動作は、AのバージョンのMを呼び出すことです(これは、new
"キーワードをB.M()
に適用した場合の動作と同じです)。
同じ名前のメソッドがあり、基本クラスから呼び出されたときの動作が異なる場合、これは「シャドウイング」と呼ばれます。
または、B.M()
で「override
」を指定することもできます。この場合、alpha.M()
はBのバージョンのMを呼び出します。
シャドーイングは、基本クラスメソッドを子クラスの新しい定義で非表示にすることで構成されます。
非表示と上書きの違いは、メソッドの呼び出し方法に関係しています。
これにより、仮想メソッドがオーバーライドされると、基本クラスのメソッド呼び出しテーブルの呼び出しアドレスが子ルーチンのアドレスに置き換えられます。
一方、メソッドが非表示になると、子クラスのメソッド呼び出しテーブルに新しいアドレスが追加されます。
問題のメソッドに対して呼び出しが行われた場合:
子クラスへの参照を使用してメソッドを呼び出した場合、動作は同じです。メソッドがオーバーライドされた場合、メソッドアドレスは基本クラスで見つかり、メソッドが非表示だった場合、メソッドアドレスは子クラスであり、すでに見つかっているため、基本クラステーブルは検索されません。
基本クラスへの参照を使用してメソッドを呼び出すと、動作が変わります。オーバーライドする場合、メソッドアドレスが基本クラスエントリを上書きするため、基本クラスへの参照を保持している場合でも、子メソッドを呼び出します。シャドウイングでは、基本クラスメソッドテーブル(基本クラスへの参照を保持しているため表示される唯一のテーブル)に仮想メソッドアドレスが含まれているため、基本クラスメソッドが呼び出されます。
一般に、シャドウイングは悪いアイデアです。これは、参照するインスタンスによってインスタンスの動作に違いが生じるためです。
ケントの正解を拡大
どのメソッドがいつ呼び出されるかを明確にするとき、シャドウイングとオーバーライドを次のように考えるのが好きです
ベースクラスメソッドを非表示にする場合は、ベースのオーバーライドを使用します[ベースの仮想メソッド]
子クラスメソッドを非表示にする場合は、ベースでnewを使用[ベースの非仮想メソッド]-> shadow
_Base B=new Child()
_
B.VirtualMethod()
->子クラスのメソッドを呼び出す
B.NonVirtualMethod()
->基本クラスメソッドの呼び出し
オーバーライド:同じ名前とまったく同じパラメーター。サブクラスで異なる方法で実装されます。
Shadowing:同じ名前とまったく同じパラメーター。サブクラスで異なる方法で実装されます。
この簡単な説明がお役に立てば幸いです。Shadowing
-親クラスの完全な要素を置き換えます
class InventoryAndSales
{
public int InvoiceNumber { get; set; }
}
//if someone calls for this class then the InvoiceNumber type is now object
class NewInventoryAndSales : InventoryAndSales
{
public new object InvoiceNumber { get; set; }
}
Overriding
-実装のみを置き換えます。たとえば、変数があるように、それがメソッドに変換しないように、置き換えられないデータ型を置き換えません。そのため、メソッドがある場合、そのメソッドを使用し、実装のみを変更します。
class InventoryAndSales
{
public virtual int GetTotalSales(int a, int b)
{
return a + b;
}
}
class NewInventoryAndSales : InventoryAndSales
{
//it replaces the implementation in parent class
public override int GetTotalSales(int a, int b)
{
return a * b;
}
}