我有以下代码。
public class Parent
{
public void Print()
{
Console.WriteLine ("Parent Method");
}
}
public class Child : Parent
{
public new void Print()
{
Console.WriteLine ("Child Method");
}
}
public class Program
{
public static void Main()
{
Child C = new Child();
C.Print();
}
}
如果我运行此代码,我会得到结果" Child Method" 但是,如果我执行以下操作,为什么我会得到结果"父方法"?
public class Parent
{
public void Print()
{
Console.WriteLine ("Parent Method");
}
}
public class Child : Parent
{
public new void Print()
{
Console.WriteLine ("Child Method");
}
}
public class Program
{
public static void Main()
{
Parent P = new Child(); // The only difference is this.
P.Print();
}
}
唯一的区别如下
Child C = new Child();
Parent P = new Child();
我认为new Child()
意味着我们创建了Child
类的实例。
我认为C
和P
都只是对象引用变量,它们保存Child
类实例的位置。
如果我错了,你可以纠正我,或者告诉我,如果我错过了什么,因为我不明白为什么在上述情况下我会得到不同的结果?
答案 0 :(得分:19)
这是因为您已在Print
中重新声明了Child
方法。因此,在编译时,P.Print()
会解析为Parent.Print
,但C.Print()
会解析为Child.Print()
。如果您在Child
中使用了重写的虚拟方法,则他们同时打印"子方法":
public class Parent
{
// Declare this as virtual, allowing it to be overridden in
// derived classes. The implementation will depend on the
// execution-time type of the object it's called on.
public virtual void Print()
{
Console.WriteLine ("Parent Method");
}
}
public class Child : Parent
{
// Override Parent.Print, so if Print is called on a reference
// with compile-time type of Parent, but at execution it
// refers to a Child, this implementation will be executed.
public override void Print()
{
Console.WriteLine ("Child Method");
}
}
相关:
override
and new
?(MSDN上的C#FAQ条目 - 原来是我写的,但我忘记了!)override
and new
keywords(MSDN)答案 1 :(得分:9)
这是引擎盖下发生的事情
Child C = new Child();
C.Print();
因为您隐藏了方法,而不是覆盖它们。所以隐藏了Parent中的Print方法,并调用了Child.Print()。
Parent P = new Child(); // The only difference is this.
P.Print();
将在父类型参考上调用此(New Child())。
如果你尝试这个,父类型引用将被转换为子类型。从此以后调用Child.Print()。
Parent P = new Child();
((Child)P).Print();
输出将是:子方法
答案 2 :(得分:4)
由于Print
方法不是virtual
,编译器不会发出代码来告诉CLR根据实际的运行时类型调用该方法。
因此,当您的变量被称为Child
时,将调用Child.Print
。但是,当您将其称为Parent
时,将使用Parent.Print
。
这里使用new
关键字仅用于 shadowing ,告诉编译器子方法确实隐藏父方法而不是压倒它,但没有效果。
答案 3 :(得分:1)
JCronin,您正在使用Parent P = new Child()投射到Parent。要获取Child类行为,您必须将其强制转换为Child(var x =(Child)P)或创建Child实例实例(Child P = new Child())。
请参阅Downcasting
答案 4 :(得分:0)
因为您将P
的类型声明为Parent
。当您为其分配Child
时,它将被转换为该类型。