理解继承(探微知著)
理解继承(探微知著)
一直在继承和多态不能完全理解,越往下想越有更多的为什么,也就越糊涂,郁闷中。。。
晚上又找到一遍关于继承的,转自http://www.rainsts.net/article.asp?id=725,继续去弄清楚剩下的为什么!
我们知道关键字 new 会阻断虚方法的继承,那么真实状况到底如何?还是像以前那样记忆几条 "飘飘忽忽" 的规则吗?
class A
{
public virtual void Test()
{
Console.WriteLine("A.Test");
}
}
class B : A
{
public override void Test()
{
Console.WriteLine("B.Text");
}
}
class C : B
{
}
public class Program
{
static void Main(string[] args)
{
C c = new C();
c.Test();
A a = c;
a.Test();
}
}
{
public virtual void Test()
{
Console.WriteLine("A.Test");
}
}
class B : A
{
public override void Test()
{
Console.WriteLine("B.Text");
}
}
class C : B
{
}
public class Program
{
static void Main(string[] args)
{
C c = new C();
c.Test();
A a = c;
a.Test();
}
}
输出:
B.Text
B.Text
上面的例子是我们要动手的目标,输出结果符合我们以往的经验和预期。
好了,接下来需要给小白鼠打针了。
class A
{
public virtual void Test()
{
Console.WriteLine("A.Test");
}
}
class B : A
{
public new void Test()
{
Console.WriteLine("B.Text");
}
}
class C : B
{
}
public class Program
{
static void Main(string[] args)
{
C c = new C();
c.Test();
A a = c;
a.Test();
}
}
{
public virtual void Test()
{
Console.WriteLine("A.Test");
}
}
class B : A
{
public new void Test()
{
Console.WriteLine("B.Text");
}
}
class C : B
{
}
public class Program
{
static void Main(string[] args)
{
C c = new C();
c.Test();
A a = c;
a.Test();
}
}
我们在 B.Test 中使用了 "new" 阻断了继承,看看这次的输出结果。
输出:
B.Text
A.Test
原因呢?
由于 B.Test 阻断了继承,并且 B.Test 已经不是虚方法了,那么被复制到 C MethodTable 中的 A.Test 自然不会被替换掉,因此 callvirt 实际执行的自然就是 A.Test 了。
看看另外一种情形。
class A
{
public virtual void Test()
{
Console.WriteLine("A.Test");
}
}
class B : A
{
public new virtual void Test()
{
Console.WriteLine("B.Text");
}
}
class C : B
{
}
public class Program
{
static void Main(string[] args)
{
C c = new C();
c.Test();
A a = c;
a.Test();
}
}
{
public virtual void Test()
{
Console.WriteLine("A.Test");
}
}
class B : A
{
public new virtual void Test()
{
Console.WriteLine("B.Text");
}
}
class C : B
{
}
public class Program
{
static void Main(string[] args)
{
C c = new C();
c.Test();
A a = c;
a.Test();
}
}
输出:
B.Text
A.Test
"new virtual" …… 这个用法很少见,不是吗?这回又会出什么 "幺蛾子" 呢?
首先,"new" 阻断了继承,因此 A.Test 不会被替换;其次,关键字 "virtual" 将 B.Test 定义成一个新的虚方法,尽管和 A.Test 同名,但完全是新的继承体系。结果吗,就是你在 C 的 MethodTable 中看到了两个被复制过来的虚方法。
依照 "最近规则",(c as C).Test 调用的自然是 B.Test,而 (c as A).Test 也只能输出 "A.Test" 了,毕竟这两丫名字虽然相同,可的的确确不是一家人。
好了,我相信此刻你对多态虚方法调用理念有了更深刻的理解,不至于云里雾里了……