继承方法无法访问派生 class 中的新实现

Inherited method has no access to new implementation in derived class

在此 MSDN article 中引用:

derived class 的类型对象无法访问从 base class 继承的新的重新定义方法以及对 [=12] 的 derived class 对象的调用=]继承的方法DescribeCar()里面的方法是对基础class.

ShowDetails()方法进行的

如果DescribeCar()方法对ConvertibleCar也可用class,怎么看不到所谓的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.

new 隐藏旧方法,这意味着如果您直接ConvertibleCar上调用它例如,您将获得派生的 class 行为,但它不会被称为 多态性

当基础 class 调用它时,它正在调用虚拟方法,因为它没有被覆盖,所以调用基础 class 方法。不要使用方法隐藏(你几乎从来没有使用过),只需覆盖它:

class ConvertibleCar : Car
{
    public override void ShowDetails()
    {
        System.Console.WriteLine("A roof that opens up.");
    }
}

好吧,当你考虑它时 - 想想 没有 继承 - 这就像问为什么 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,因此无法调用该方法。

其他答案都是正确的,但我想举例说明 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 调用新实现的唯一方法是将您的变量转换为定义新实现的类型。