派生类可以访问基类方法,所以当在派生类实例上调用基类方法时,它实际上是使用派生类实例还是在幕后使用基类实例,因为我们知道派生类是初始化,它也初衷了它的基础。
考虑下面的例子,虽然它是虚拟/新的一部分,但是当看到这个问题时会想到这个问题。
class Car
{
public void DescribeCar()
{
System.Console.WriteLine("Four wheels and an engine.");
ShowDetails();
}
public virtual void ShowDetails()
{
System.Console.WriteLine("Standard transportation.");
}
}
class ConvertibleCar : Car
{
public new void ShowDetails()
{
System.Console.WriteLine("A roof that opens up.");
}
}
ConvertibleCar car2 = new ConvertibleCar();
car2.DescribeCar();
所以当我们这样做时,基类" ShowDetails()"即使实例是派生类,也会调用它。
所以在幕后,它是否使用基类实例。当我们"覆盖" ConvertibeCar showdetails即覆盖派生类方法然后它调用派生类" showdetails()"
答案 0 :(得分:0)
子类中重写方法的重点在于子类的方法将在运行时执行,即使编译时类型是超类的类型。
如果由于某种原因需要超类的实例,则应该向超类添加一个复制构造函数并使用它来创建这样的实例:
public class Base {
...
...
Base (Base source) {
// copy the properties
}
}
然后:
public void makeStr(Derived d){
Base b = new Base(d);
...
b.getStr() will call the Base class implementation
}
答案 1 :(得分:-1)
如果我们检查为主程序生成的IL,看起来它使用Car
实例进行调用:
C#代码:
class ConvertibleCar : Car
{
}
和IL:
IL_0000: nop
IL_0001: newobj UserQuery+ConvertibleCar..ctor
IL_0006: stloc.0 // car
IL_0007: ldloc.0 // car
IL_0008: callvirt UserQuery+Car.ShowDetails
IL_000D: nop
IL_000E: ret
当我们在ShowDetails
中实现ConvertibleCar
时,它正在使用这个类实例:
class ConvertibleCar : Car
{
public new void ShowDetails()
{
System.Console.WriteLine("A roof that opens up.");
}
}
然后生成的IL看起来像:
IL_0000: nop
IL_0001: newobj UserQuery+ConvertibleCar..ctor
IL_0006: stloc.0 // car
IL_0007: ldloc.0 // car
IL_0008: callvirt UserQuery+ConvertibleCar.ShowDetails
IL_000D: nop
IL_000E: ret
是的,我从IL生成器中清除了ConvertibleCar
的构造函数,Car
构造函数也被称为:
ConvertibleCar..ctor:
IL_0000: ldarg.0
IL_0001: call UserQuery+Car..ctor
IL_0006: ret