2017-03-22 10 views
0

出力を理解できません。私は次のコードを実行したときに私はBダイナミック多型の奇妙な出力

午前、私は次の出力を取得し、今

1を


A a1 = new PolymorphismInDepth.B(); 
     a1.Print(); 
     Console.WriteLine(a1.i); 

を二つのクラス、

class A 
{ 
    public int i = 1; 

    public virtual void Print() 
    { 
     Console.WriteLine("I am A"); 
    } 
} 

class B:A 
{ 
    public int i =2 ; 

    public override void Print() 
    { 
     i++; 
     Console.WriteLine("I am B"); 
    } 

} 

を以下しています


なぜ1になるのですか?なぜ2ではない?

答えて

2

基本クラスオブジェクトa1は、メモリ内の派生オブジェクトを指しています。したがってa1.Print()はメソッド参照、つまりB().Print()を呼び出しますが、このA().iを使用してB().iにアクセスすることはできません。

あなたはそれをキャストする必要があります。

Console.WriteLine(((B)a1).i); 

あなたは同じ変数名を使用するので、あなたが混乱しています。これを試してみてください:このようなbiにアクセスしようとし

class A 
{ 
    public int ai = 1; 

    public virtual void Print() 
    { 
     Console.WriteLine("I am A"); 
    } 
} 

class B : A 
{ 
    public int bi = 2; 

    public override void Print() 
    { 
     bi++; 
     Console.WriteLine("I am B"); 
    } 

} 

static void Main(string[] args) 
{ 
    A a1 = new B(); 
    a1.Print(); 
    Console.WriteLine(a1.ai); 
    Console.WriteLine(((B)a1).bi); 
    Console.Read(); 
} 

はあなたのコンパイル時のエラーを与える必要があります。

Console.WriteLine(a1.bi); //ERROR: 'A' does not contain a definition for 'bi'... 

更新:

解答へ追加する - などの実装これは、ベースクラスのメンバ変数の動作をオーバーライドすることもできます:

class A 
{ 
    private int i = 1; 
    public virtual int I 
    { 
     get { return i; } 
    } 

    public virtual void Print() 
    { 
     Console.WriteLine("I am A"); 
    } 
} 

class B : A 
{ 
    private int i = 2; 

    public override int I 
    { 
     get { return i; } 
    } 
    public override void Print() 
    { 
     i++; 
     Console.WriteLine("I am B"); 
    } 

} 


A a1 = new B(); 
a1.Print(); 
Console.WriteLine(a1.I); 
Console.WriteLine(((B)a1).I); 

出力:サディクが言ったことに加えて

I am B

3

3

+0

基本クラスのメンバA()。iを隠すように、わかりやすく説明してください。 –

+0

B.iはA.iとは無関係の新しい変数です。ちょうど同じ名前を持つことになります(名前を変更することでうまく対応しています)。 –

+0

@ PetA。シュナイダー - 私はそれを考えました、実際には単純ではありません。名前が同じであるために問題が発生しなかったが、問題は、 'A 'によって提供されたインタフェースがコンパイル時に' B'の項目にアクセスできないということである。 OPの前提は、同じ変数名を持つと、派生したオブジェクトの変数へのアクセスが可能になるということでした。これは必ずしも変数名とは関係ありません。 – Sadique

0

。クラスをパブリックとしてマークしてビルドすると、クラスBの変数iに何かを示すエディタが表示されます。ベースメンバーIを隠していて、newキーワードでオーバーライドする必要があります。

public int i = 2;を削除すると、クラスBからは、基本変数を変更するときに出力が2になります。しかし、あなたはBで私の新しいを宣言した場合、あなたは私が現在のコードでそうB.

に新しいの別々のスコープを作成しているあなたはラインConsole.WriteLine(a1.ai); にデバッガを置けばそれは明らか値と値1と他の2つのI変数のいずれかを示してい2.値2はタイプBのためです。したがって、Bのインスタンスからiを参照しているときにのみ2を取得します。

これが疑問を解消することを願っています。