Inherited方法无法访问派生类中的新实现

时间:2015-03-25 17:01:39

标签: c# inheritance methods method-hiding

在此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.

3 个答案:

答案 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."
}

tConvertibleCar,因为它是对象的实际类型,但this变量(实际上是编译器隐藏的每个非静态方法的参数)是类型为Car

关于virtual方法的具体事情是,当你的代码调用它们时,编译器会在对象的实际类型上进行额外的查找(即调用GetType())并检查是否有任何类型在您的层次结构中已覆盖该方法。然后它调用您方法的最新实现。 但是,如果您使用new而不是override,则此查找不会产生任何结果,并且会使用基本实现。如果使用new,则调用新实现的唯一方法是将变量强制转换为定义新实现的类型。