2017-09-03 77 views
2

我想了解C#中继承的基础知识,并意识到我对范围和可访问性的理解存在差距。一个例子来说明:当覆盖vs隐藏基类方法时C#范围差异

using System.Windows.Forms; 

namespace InheritanceTests { 
    class Program { 
     public static void Main() { 
      (new A()).Foo();  // A: 1 
      (new B()).Foo();  // B: 2 
      ((A)(new B())).Foo(); // B: 2 (+) 
      (new C()).Foo();  // C: 3 
      ((A)(new C())).Foo(); // A: 1 (++) 
     } 
    } 
    class A { 
     private int x = 1; 
     public virtual void Foo() { MessageBox.Show("A: " + this.x); } 
    } 
    class B : A { 
     private int x = 2; 
     public override void Foo() { MessageBox.Show("B: " + this.x); } 
    } 
    class C : A { 
     private int x = 3; 
     public new void Foo() { MessageBox.Show("C: " + this.x); } 
    } 
} 

我有问题(+)和(++),很可能涉及:

关于(+),为什么是B实例的私有字段x访问即使投到A

关于(++),为什么当AFoo方法执行时this.x没有评估为3?

回答

0

关于(+),为什么B实例的私有字段x即使在转换为A后也可以访问?

接触谁?在你的例子中,B.Foo()被调用,因为B已被覆盖A.Foo()(这是virtual)。由于所调用的方法实际上在类别B中,所以该方法使用在B中声明的x字段。这是该方法可以看到的唯一字段x

该字段xAB无效,因为它是private。但是,如果它是(即如果它比其他private东西),在B领域x将其隐藏和B实施Foo()将仍然使用xB类,而不是从A

关于(++),为什么当A的Foo方法执行时,this.x不会评估为3?

在这个例子中,派生类C具有A重写原来的方法Foo()。相反,它被宣布为一个全新的方法Foo()。但是通过将对象转换回A,编译器不再知道在C中声明的方法。它可以看到的唯一方法是A.Foo(),这是而不是重写,因此调用Foo()A执行。

当然,该实现只能看到在A中声明的x字段,其​​中声明了方法本身。因此,您在输出中获得1而不是3