C#-明示的な界面との相続?
-
13-09-2019 - |
質問
出力:
B->こんにちは!から顕在化する。
ながれ:?
A->こんにちは!から顕在化する。
が記載されていないのはなぜ明示的にキャスト(IHello)の呼び出IHello.こんにちは()からクラス。
interface IHello
{
void Hello();
}
class A : IHello
{
public virtual void Hello()
{
Console.WriteLine("A->Hello!");
}
void IHello.Hello()
{
Console.WriteLine("A->Hello! from Explicit.");
}
}
class B : A, IHello
{
public override void Hello()
{
Console.WriteLine("B->Hello!");
}
void IHello.Hello()
{
Console.WriteLine("B->Hello! from Explicit.");
}
}
class Program
{
static void Main(string[] args)
{
A a = new B();
((IHello)a).Hello();
}
}
解決
いいえ、いよいと思います。
を呼び出 Hello
同氏-ひとつのルートを IHello
なのないかぎり、実行する必要があの時の確認または変換);のコンパイル時の型は IHello
もしかしたら、インターフェースのマッピングは同じとします。
がインターフェースは明示的に実施回以上の階層型の実装に由来タイプを使用します。(そういうわけで、これをインターフェース。)
から部13.4.4のC#3.0仕様:
タマッピングのためのクラスまたは struct C置を実施 各メンバーの各インタフェース 指定された基底クラスのリストCの実装に特定の インタ員I.M,Iを インタフェースの会員はM 宣言された定めによる検討 各クラスまたはstruct S開始 Cを繰り返し毎に歴代の の基底クラスCまでの間、試合は ホ:
- そうでない場合、Sが含まれて宣言 の明示的なインタ員 実施に合っとM そしてこの委員は、実装 の研究
- そうではない場合、Sが含まれて宣言への非公開の会員と一致するM、そしてこの委員は、実施の研究場合により試合では指定される委員は、実施の研究この状況をできるだけた場合に生じる"S"は構築型を会員として宣言した汎用タイプの異なる署名の型引数を署名と同一です。
他のヒント
(A)Aは何もしません。参照がまだAにキャストすることは効果がありませんように宣言されます。
あなたはIHelloにこのオブジェクトをキャストする場合は、あなたの参照は、Aとして宣言されていても、それが参照するオブジェクトは、タイプBのものであり、こんにちは()の呼び出しでは、ハローのオブジェクトBの明示的な実装を呼び出します。
出力が期待どおりにある。
いいえ、それは仮想ではありません。新はちょうどあなたが、基本クラスでバージョンを「隠し」、それを気にしないことを意味します - ので、あなたは、特定のタイプ(A)にキャストしていることを参照して、それを呼び出す場合、それは関係なく、クラスAにメソッドを実行しますあなたが呼び出しているオブジェクトの実際の型。 (すなわちあなたがA.ToString(と呼ばれる)ので、それはA.ToStringを実行する())
するときは、その後の仮想の方法、あなたが呼ばれたときにタイプに関係なく何のあなたがへの参照をキャストし、オブジェクトの実際の型からの実装が使用されている(つまり、あなたがそう、Bを作成を作成します.Hello(対象が何であれ)、それが呼ばれるB.Hello)
決定的な違いは、1つのコールが仮想であり、他はないということです。
いいえ、それはいけない。
あなたは仮想メソッドを呼び出している場合は、、参照の型が何であるかは重要ではありません。呼び出されるメソッドは、オブジェクトの実際の型ではなく、参照のタイプによって決定されます。
あなたはクラスB
のインスタンスを作成すると、、オブジェクトの実際の型はB
です。それは"This is class A."
を印刷した理由は、あなたがクラスToString
でB
メソッドをオーバーライドしていないということです、あなたはnew
キーワードを使用して、それを影にしています。従ってB
クラスは、二つToString
メソッド、クラスA
及びそれをシャドウ一方から継承つを有します。あなたはA
メソッドを呼び出すためにToString
リファレンスを使用する場合は、継承されたメソッドが呼び出されますが、あなたはそれを呼び出すためにB
参照を使用していたならば、シャドウイング方式は"This is class B."
をプリントアウトし、呼び出されます。
また、あなたが代わりにそれをシャドウイングのクラスToString
でB
メソッドをオーバーライドした場合、それは参照の種類に関係なく"This is class B."
をプリントアウトします。