我正在尝试学习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
之后也可以访问?
关于(++),执行A
的{{1}}方法的原因是Foo
不评估为3?
答案 0 :(得分:0)
关于(+),为什么B实例的私有字段x即使在转换为A之后也可以访问?
可以访问谁?在您的示例中,B.Foo()
被调用,因为B
已覆盖A.Foo()
(virtual
)。由于被调用的方法实际上在类B
中,因此该方法使用x
中声明的B
字段。这是该方法可以看到的唯一字段x
。
x
中的A
字段无论如何都不可见B
,因为它private
。但如果是(即如果它不是private
),x
中的字段B
会隐藏它,而B
的{{1}}实现会仍然使用Foo()
课程中的x
,而不是B
。
关于(++),为什么在执行A&#39的Foo方法时,this.x不能评估为3?
在此示例中,派生类A
的不会覆盖C
中的原始方法Foo()
。相反,它宣布了一种全新的方法A
。但是通过将对象强制转换回Foo()
,编译器不再知道A
中声明的方法。它可以看到的唯一方法是C
,不被覆盖,因此A.Foo()
的{{1}}实现被调用。
当然,该实现只能看到A
中声明的Foo()
字段,其中声明了方法本身。因此,您在输出中得到x
而不是A
。