回答:
相続...
次のクラスがあるとします。
class A {
public int Foo(){ return 5;}
public virtual int Bar(){return 5;}
}
class B : A{
public new int Foo() { return 1;} //shadow
public override int Bar() {return 1;} //override
}
次に、これを呼び出すと:
A clA = new A();
B clB = new B();
Console.WriteLine(clA.Foo()); // output 5
Console.WriteLine(clA.Bar()); // output 5
Console.WriteLine(clB.Foo()); // output 1
Console.WriteLine(clB.Bar()); // output 1
//now let's cast B to an A class
Console.WriteLine(((A)clB).Foo()); // output 5 <<<-- shadow
Console.WriteLine(((A)clB).Bar()); // output 1
基本クラスがあり、継承されたクラスの代わりにすべてのコードで基本クラスを使用し、シャドウを使用すると、オブジェクトの実際の型の継承ツリーをたどるのではなく、基本クラスが返す値が返されます。
私が理解していることを願っています:)
シャドウイングは、実際にはC#で非表示と呼ばれるもののVB用語です。
多くの場合、Stormenetによる回答のように、非表示(VBでのシャドウイング)とオーバーライドが表示されます。
仮想メソッドはサブクラスによってオーバーライドされることが示され、スーパークラスタイプまたはスーパークラスの内部コードからでもそのメソッドを呼び出すと、サブクラスから置換実装が呼び出されます。
次にnew
、サブクラスで同じシグネチャを持つメソッドを定義するときに、キーワードを使用して非表示になっている具象メソッド(仮想または抽象としてマークされていないメソッド)が表示されます。この場合、メソッドがスーパークラスタイプで呼び出されると、元の実装が使用され、新しい実装はサブクラスでのみ使用できます。
ただし、見落とされることが多いのは、仮想メソッドを非表示にすることもできるということです。
class A
{
public virtual void DoStuff() { // original implementation }
}
class B : A
{
public new void DoStuff() { //new implementation }
}
B b = new B();
A a = b;
b.DoStuff(); //calls new implementation
a.DoStuff(); //calls original implementation.
上記の例では、DoStuffが具象になり、オーバーライドできないことに注意してください。ただし、virtual
およびnew
キーワードの両方を一緒に使用することもできます。
class A
{
public virtual void DoStuff() { // original implementation }
}
class B : A
{
public new virtual void DoStuff() { //new implementation }
}
class C : B
{
public override void DoStuff() { //replacement implementation }
}
C c = new C();
B b = c;
A a = b;
c.DoStuff(); //calls replacement implementation
b.DoStuff(); //calls replacement implementation
a.DoStuff(); //calls original implementation.
関連するすべてのメソッドが仮想であってもnew
、B での使用はAの実装を非表示にするため、CのオーバーライドはAの仮想メソッドには影響しません。
編集:この回答に対するコメントで、上記は危険であるか、少なくとも特に有用ではない可能性があることが指摘されています。私はそう言うのは危険である可能性があり、もしそれが少しでも役に立つならそこに出て行くでしょう。
特に、アクセシビリティ修飾子も変更すると、さまざまな問題が発生する可能性があります。例えば:-
public class Foo
{
internal Foo() { }
protected virtual string Thing() { return "foo"; }
}
public class Bar : Foo
{
internal new string Thing() { return "bar"; }
}
外部相続にBar
、Foo
シング()のの実装では、づけし及びオーバーライド残ります。.NETタイプのルールに従ってすべての合法で説明可能なことは、決して直感的ではありません。
この回答を掲載して、自由に使用できる手法の提案ではなく、物事の仕組みについての理解を深めました。
主な違いは、シャドウイングでは、本質的に名前を再利用し、スーパークラスの使用を無視することです。オーバーライドすると、実装は変更されますが、アクセシビリティと署名は変更されません(たとえば、パラメーターの型と戻り値)。http://www.geekinterview.com/question_details/19331を参照してください。
基本的に以下のようなものがあれば、
Class A
{
}
Class B:A
{
}
A a = new B();
オブジェクト 'a'で呼び出すメソッドはすべて 'a'のタイプで作成されます(ここでタイプは 'A'です)。ただし、クラスAにすでに存在するクラスBに同じメソッドを実装すると、コンパイラーは「新しい」キーワードを使用するよう警告します。「新規」を使用すると、警告が消えます。これ以外は、継承されたクラスで「新規」を使用するか使用しないかの違いはありません。
状況によっては、オブジェクトタイプのメソッドを呼び出す代わりに、特定のインスタンスがその時点で保持している参照クラスのメソッドを呼び出す必要がある場合があります。上記の場合、それが保持する参照は「B」ですが、タイプは「A」です。したがって、メソッド呼び出しを「B」で行う必要がある場合は、Virtualとオーバーライドを使用してこれを実現します。
お役に立てれば...
ダニエル・サンディープ。
クラスの内容を変更できない場合があるとしましょう。たとえばA
、いくつかのメソッドを使用したいが、共通の名前を持つメソッドがある場合は、new
キーワードによって独自のメソッド実装を使用できます。
重要なポイントは、参照とオブジェクトの両方が同じタイプでなければならないということです。
class A
{
public void Test()
{
Console.WriteLine("base");
}
}
class B : A
{
public new void Test()
{
Console.WriteLine("sub");
}
public static void Main(string[] args)
{
A a = new A();
B aa = new B();
a.Test();
aa.Test();
}
}