我可以理解基本的对象切片,但有时它会变得很混乱 当我们来到像那样的例子时
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” 请帮我解决这个问题
答案 0 :(得分:5)
嗯,AMAIK,你的问题基本上不是关于对象切片。它更多的是使用new
,virtual
和override
关键字之间的区别。
我将提出一个更容易理解的例子。请考虑以下代码:
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.");
}
}
现在让我们分析每个关键字。由于Worker
基本上基本上是人类,因此HasBreasts
也可以FallInLove()
。但是等一下。一个工人(没有冒犯,只是一个有趣的例子)没有钱坠入爱河。然后一个工人可能会override
这种行为,忘记爱情。
另一方面,所有动物都可以睡觉。他们只是闭上眼睛睡觉。然而,由于哺乳动物是热血动物,它们需要一个温暖的地方。所以他们延长了祖先的睡眠习惯。
但另一方面,人类定义了完全new
的睡眠水平。他想要对他的祖先进行革命。他不想被称为Animal
,所以他从头开始重新定义Sleep()
。
现在根据@DanPuzey的解释,您可以阅读其余的故事。它在现实世界中是有道理的。
答案 1 :(得分:4)
当您使用new
定义与基类方法同名的方法时,您隐藏基类的实现。 (这几乎总是一个坏主意,但偶尔也是必要的。)
当您使用这样的隐藏方法引用类时,它不是覆盖。因此,用于引用对象的变量类型将决定您将获得的方法版本。
当您通过new D()
或a
引用b
时,您将其引用为不了解该方法的new
版本的类型。因此,这两个调用都使用他们 知道的方法的派生版本。 B.F()
中的C
没有覆盖(因为它是new
)或D
(因为它只会覆盖C
中的方法)。因此,在这两种情况下都会调用B.F()
。
当您通过c
或d
引用该课程时,会使用D
中的重写方法,如您所料。