理解继承(探微知著)

理解继承(探微知著)

     一直在继承和多态不能完全理解,越往下想越有更多的为什么,也就越糊涂,郁闷中。。。

     晚上又找到一遍关于继承的,转自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();
  }
}

输出:
B.Text
B.Text

上面的例子是我们要动手的目标,输出结果符合我们以往的经验和预期。

uploads/200807/01_212825_1.gif


好了,接下来需要给小白鼠打针了。
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();
  }
}

我们在 B.Test 中使用了 "new" 阻断了继承,看看这次的输出结果。

输出:
B.Text
A.Test

原因呢?

uploads/200807/01_212830_2.gif


由于 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();
  }
}

输出:
B.Text
A.Test

"new virtual" …… 这个用法很少见,不是吗?这回又会出什么 "幺蛾子" 呢?

uploads/200807/01_212835_3.gif


首先,"new" 阻断了继承,因此 A.Test 不会被替换;其次,关键字 "virtual" 将 B.Test 定义成一个新的虚方法,尽管和 A.Test 同名,但完全是新的继承体系。结果吗,就是你在 C 的 MethodTable 中看到了两个被复制过来的虚方法。

依照 "最近规则",(c as C).Test 调用的自然是 B.Test,而 (c as A).Test 也只能输出 "A.Test" 了,毕竟这两丫名字虽然相同,可的的确确不是一家人。

好了,我相信此刻你对多态虚方法调用理念有了更深刻的理解,不至于云里雾里了……
posted @ 2008-09-10 00:00  divingmaomao  阅读(327)  评论(1编辑  收藏  举报