0

我可以理解基本的对象切片,但有时当我们遇到这样的例子时会变得很混乱

using System;
class A
{
   public virtual void F() { Console.WriteLine("A.F"); }
}
class B: A
{
   public override void F() { Console.WriteLine("B.F"); }
}
class C: B
{
   new public virtual void F() { Console.WriteLine("C.F"); }
}
class D: C
{
   public override void F() { Console.WriteLine("D.F"); }
}
class Test
{
   static void Main() {
      D d = new D();
      A a = d;
      B b = d;
      C c = d;
      a.F();
      b.F();
      c.F();
      d.F();
   }
}

输出 :

B.F
B.F
D.F
D.F

我想知道B类的“f()”函数是如何实现的

D d = new D();
A a = d;
a.F();

如果是的话:

A a = new A();
a.F()
//The result would be => A.F  

但是在第一部分中,“a”有一个“d”的运行时对象,所以有人可能认为它是“DF”作为输出,所以它是如何出现在 D、c 和 B 中的,所以正确的输出是“BF”请帮我解决这个问题

4

2 回答 2

5

好吧,AMAIK,您的问题本质上与对象切片无关。new它更多地是关于使用,virtualoverride关键字之间的区别。

我将提出一个更容易理解的例子。考虑这段代码:

public class Animal
{
    public virtual void Sleep()
    {
        Console.WriteLine(@"I'm an animal, and I want to sleep.
        I just close my eyes");
    }
}

public class Mammal : Animal
{
    public override void Sleep()
    {
        Console.WriteLine(@"I'm a mammal, thus basically an animal.
        Therefore, I both close my eyes, and need a warm place to sleep");
    }

    public bool HasBreasts
    {
        get
        {
            return true;
        }
    }
}

public class Human : Mammal
{
    public new virtual void Sleep()
    {
        Console.WriteLine(@"I'm a human. 
        I'm so proud that I don't consider myself as an animal. 
        I sleep in a cozy place, 
        and I need a lot of money to sleep well");
    }

    public virtual void FallInLove();
}

public class Worker : Human
{
    public override void Sleep()
    {
        Console.WriteLine(@"I'm a worker, and I'm under poverty line. 
        I have to work hard, 
        and I really don't know what they mean by a good sleep");
    }

    public override void FallInLove()
    {
        Console.WriteLine(@"What is love? 
        I need bread to survive. 
        I'm in the bottom-most level of Mozlow's pyramid of needs.");
    }
}

现在让我们分析每个关键字。由于 aWorker基本上和本质上是一个人,因此它HasBreasts和它也可以FallInLove()。但是等一下。一个工人(无意冒犯,只是一个有趣的例子)没有钱谈恋爱。然后一个工人可能会override这种行为,而忘记爱。

另一方面,所有动物都可以睡觉。他们只是闭上眼睛睡觉。然而,由于哺乳动物是热血动物,它们需要一个温暖的地方。所以他们延续了祖先睡觉的习惯。

但另一方面,人类定义了一个完整new的睡眠水平。他想要一场反对他祖先的革命。他不想被称为 an Animal,所以他Sleep()从头开始重新定义。

现在根据@DanPuzey 的解释,您可以阅读故事的其余部分。这在现实世界中是有意义的。

于 2013-11-14T14:15:55.100 回答
5

当您使用new定义与基类的方法同名的方法时,您隐藏了基类的实现。(这几乎总是一个坏主意,但偶尔是必要的。)

当您使用这样的隐藏方法引用一个类时,它不是覆盖。因此,您用来引用对象的变量类型将决定您将获得哪个版本的方法。

当您new D()通过aor引用您的时b,您将其引用为不知道new该方法版本的类型。因此,这两个调用都使用了他们所知道的最衍生版本的方法。B.F()in没有覆盖C(因为它是new)或D(因为它只覆盖了 in 的方法C)。因此,B.F()在这两种情况下都会调用。

c当您通过or引用该类时d,将使用覆盖的方法 in D,正如您所期望的那样。

于 2013-11-14T14:02:29.770 回答