1

正如此MSDN 文章中所引用的:

派生类的类型对象无法访问从基类继承的重新定义的新方法,继承的ShowDetails()Method内部的Method对派生类对象的调用是对基类DescribeCar()ShowDetails()Method进行的。

如果DescribeCar()Method也是ConvertibleCar类可用的,怎么就看不到所谓的new ShowDetails()Method呢?

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.
4

3 回答 3

4

new 隐藏了旧方法,也就是说如果直接在实例上调用ConvertibleCar,会得到派生类的行为,但不会被多态调用。

当基类调用它时,它调用的是虚方法,因为它没有被覆盖,所以调用了基类方法。而不是使用方法隐藏(你几乎从不使用),只需覆盖它:

class ConvertibleCar : Car
{
    public override void ShowDetails()
    {
        System.Console.WriteLine("A roof that opens up.");
    }
}
于 2015-03-25T17:05:04.277 回答
1

好吧,当你考虑它时——想想没有继承——这就像问为什么Car.DescribeCar不能访问ConvertibleCar.ShowDetails.

ConvertibleCar.ShowDetails本质上是一种方法,Car如果您愿意,它不是成员 - 因为new关键字。Car不过有个方法ShowDetails

Car.DescribeCar作为 , 的成员方法Car,具有Car.ShowDetails和 not的可见性ConvertibleCar.ShowDetails,因此Car.ShowDetails是被调用的。

也许这会更清楚。使用new关键字,这是另一种思考方式:

class Car
{
  ...
  public virtual void ShowDetails(){..}
}

class ConvertibleCar : Car
{
  public void new_ShowDetails(){}
}

Car不知道ConvertibleCar.new_ShowDetails所以不能调用该方法。

于 2015-03-25T17:11:03.260 回答
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调用新实现的唯一方法是将变量转换为定义新实现的类型。

于 2015-03-25T17:39:30.853 回答