在此MSDN article中引用:
派生类的类型对象无法访问从基类继承的新重定义方法,并且从ShowDetails()
对派生类的对象进行调用继承方法DescribeCar()
内的方法到基类的ShowDetails()
方法。
如果DescribeCar()
类也可以使用ConvertibleCar
方法,那怎么会看不到所谓的new ShowDetails()
方法?
class Car
{
public void DescribeCar()
{
System.Console.WriteLine("Four wheels and an engine.");
ShowDetails();
}
public virtual void ShowDetails()
{
System.Console.WriteLine("Standard transportation.");
}
}
// Define the derived classes.
// Class ConvertibleCar uses the new modifier to acknowledge that ShowDetails
// hides the base class method.
class ConvertibleCar : Car
{
public new void ShowDetails()
{
System.Console.WriteLine("A roof that opens up.");
}
}
class Program
{
static void Main(string[] args)
{
ConvertibleCar car2 = new ConvertibleCar();
car2.DescribeCar();
}
}
//output
// Four wheels and an engine.
// Standard transportation.
答案 0 :(得分:4)
new
隐藏旧方法,这意味着如果直接在ConvertibleCar
实例上调用它,您将获得派生类行为,但它不会被称为多态。
当基类调用它时,它调用虚方法,因为它没有被覆盖,所以调用基类方法。而不是使用方法隐藏(你几乎永远不会使用它),只需覆盖它:
class ConvertibleCar : Car
{
public override void ShowDetails()
{
System.Console.WriteLine("A roof that opens up.");
}
}
答案 1 :(得分:1)
好吧,当你考虑它时 - 想想没有继承 - 这就像问Car.DescribeCar
无法访问ConvertibleCar.ShowDetails
的原因。
ConvertibleCar.ShowDetails
本质上是一种方法,如果您愿意,它不是Car
的成员 - 因为new
关键字。 Car
但是有一个方法ShowDetails
。
Car.DescribeCar
作为Car
的成员方法,可见Car.ShowDetails
而不是ConvertibleCar.ShowDetails
,因此Car.ShowDetails
会被调用。
也许这会更清楚。使用new
关键字,这是另一种思考方式:
class Car
{
...
public virtual void ShowDetails(){..}
}
class ConvertibleCar : Car
{
public void new_ShowDetails(){}
}
Car
不了解ConvertibleCar.new_ShowDetails
,因此无法调用此方法。
答案 2 :(得分:0)
其他答案都是正确的,但我想展示DescribeCar()
方法中发生的事情的一个例子。
public void DescribeCar()
{
Type t = this.GetType();
//bad hack
dynamic _this = Convert.ChangeType(this, t);
this.ShowDetails(); //Prints "Standard transportation."
_this.ShowDetails(); //Prints "A roof that opens up."
}
t
是ConvertibleCar
,因为它是对象的实际类型,但this
变量(实际上是编译器隐藏的每个非静态方法的参数)是类型为Car
。
关于virtual
方法的具体事情是,当你的代码调用它们时,编译器会在对象的实际类型上进行额外的查找(即调用GetType()
)并检查是否有任何类型在您的层次结构中已覆盖该方法。然后它调用您方法的最新实现。
但是,如果您使用new
而不是override
,则此查找不会产生任何结果,并且会使用基本实现。如果使用new
,则调用新实现的唯一方法是将变量强制转换为定义新实现的类型。