web-dev-qa-db-ja.com

シャドーイングとは何ですか?

C#では、用語shadowingはどういう意味ですか? このリンク を読みましたが、完全には理解していません。

34
james

シャドウイングは、基本クラスのメソッドを隠します。リンクした質問の例を使用して:

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キーワードで行われます。

上記のコードで、クラスFooBメソッドを定義するときにnewキーワードを使用しなかった場合、次のコンパイラ警告が表示されます。

'test.B.Foo()' hides inherited member 'test.A.Foo()'. Use the new keyword if hiding was intended.
45
Jim Mischel
  • オーバーライド:基本クラスで既存のメソッドを再定義する
  • シャドウイング:基本クラスのメソッドと同じシグネチャを持つまったく新しいメソッドを作成する
32
Kent Boogaart

仮想メソッドを実装する基本クラスがあるとします:

_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を呼び出します。

20
mqp

シャドーイングは、基本クラスメソッドを子クラスの新しい定義で非表示にすることで構成されます。

非表示と上書きの違いは、メソッドの呼び出し方法に関係しています。

これにより、仮想メソッドがオーバーライドされると、基本クラスのメソッド呼び出しテーブルの呼び出しアドレスが子ルーチンのアドレスに置き換えられます。

一方、メソッドが非表示になると、子クラスのメソッド呼び出しテーブルに新しいアドレスが追加されます。

問題のメソッドに対して呼び出しが行われた場合:

  1. メソッド呼び出しテーブルクラスタイプが取得されます。ベースクラスへの参照で呼び出している場合はベースクラスメソッドテーブルが取得され、子クラスへの参照がある場合は子クラスメソッドテーブルが取得されます。
  2. メソッドはテーブル内で検索され、見つかった場合は呼び出しが行われ、そうでない場合は基本クラスのメソッドテーブルが検索されます。

子クラスへの参照を使用してメソッドを呼び出した場合、動作は同じです。メソッドがオーバーライドされた場合、メソッドアドレスは基本クラスで見つかり、メソッドが非表示だった場合、メソッドアドレスは子クラスであり、すでに見つかっているため、基本クラステーブルは検索されません。

基本クラスへの参照を使用してメソッドを呼び出すと、動作が変わります。オーバーライドする場合、メソッドアドレスが基本クラスエントリを上書きするため、基本クラスへの参照を保持している場合でも、子メソッドを呼び出します。シャドウイングでは、基本クラスメソッドテーブル(基本クラスへの参照を保持しているため表示される唯一のテーブル)に仮想メソッドアドレスが含まれているため、基本クラスメソッドが呼び出されます。

一般に、シャドウイングは悪いアイデアです。これは、参照するインスタンスによってインスタンスの動作に違いが生じるためです。

10
Jorge Córdoba

ケントの正解を拡大

どのメソッドがいつ呼び出されるかを明確にするとき、シャドウイングとオーバーライドを次のように考えるのが好きです

  • シャドーイング:呼び出されるメソッドは、呼び出しが行われた時点での参照のタイプによって異なります
  • オーバーライド:呼び出されるメソッドは、呼び出しが行われた時点のオブジェクトのタイプによって異なります。
8
JaredPar

シャドウイングに関する MSDN記事 があります。言語の例はVisual Basicにあります(残念ながら、MSDNには同等のC#ページはありません)が、一般的には概念を扱っており、とにかく理解するのに役立つはずです。

編集:そこにあるようですisa C#article C#ではhidingと呼ばれます。また、 このページ は概要を示しています。

3
Noldorin

ベースクラスメソッドを非表示にする場合は、ベースのオーバーライドを使用します[ベースの仮想メソッド]

子クラスメソッドを非表示にする場合は、ベースでnewを使用[ベースの非仮想メソッド]-> shadow

_Base B=new Child()
_

B.VirtualMethod()->子クラスのメソッドを呼び出す

B.NonVirtualMethod()->基本クラスメソッドの呼び出し

2
Mathew M

オーバーライド:同じ名前とまったく同じパラメーター。サブクラスで異なる方法で実装されます。

  • DerivedClassまたはBaseClassとして扱われる場合、派生メソッドを使用しました。

Shadowing:同じ名前とまったく同じパラメーター。サブクラスで異なる方法で実装されます。

  • DerivedClassとして扱われる場合、派生メソッドを使用しました。
  • baseClassとして扱われる場合、ベースメソッドを使用します。
0
Kamran Bigdely

この簡単な説明がお役に立てば幸いです。

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;
        }
    }
0
davinceleecode