了解覆盖和新属性

时间:2018-08-12 23:47:15

标签: c# polymorphism override new-operator virtual-inheritance

    class Car
    {
        public virtual string Name { get; set; }

        public virtual void CheckName()
        {
            throw new NotImplementedException();
        }

    }

class ConveribleCar : Car
{
    public override string Name { get; set; }

    public override  void CheckName()
    {
        Console.WriteLine("this :{0} , base : {1}", this.Name, base.Name); 
    }

}

class Minivan : Car
{
    public new string Name { get; set; }

    public override void CheckName()
    {
        Console.WriteLine("this :{0} , base : {1}", this.Name, base.Name);
    }
}


and the calling code : 
Car car = new Minivan(){Name = "Minivan"};//using new property
Car car2 = new ConveribleCar(){Name = "Convertible"};//using override property
car.CheckName(); //prints this : Minivan, base : (null or empty)
car2.CheckName(); //prints this : Convertible , base :(null or empty)

我了解方法中的虚拟化原理,如果您使用关键字new将其隐藏在派生类中, 如果您使用覆盖,则新的实现将被计入其中,并且使用该实现,但是我不明白为什么这种情况不会发生 具有属性,根据我的理解,我应该期望汽车中的base.Name应该打印“ Minivan”(因为正在将Minivan类中的派生Name隐藏)​​,并且this.Name将为null。 (据我所知)

此外,当我检查VS car.Name中的对象car时,即使它显示“ Minivan”,它也为null,这种行为对我来说真的很奇怪。 任何人都可以给我解释示例代码中发生的事情,或者任何人都可以提出一个更好的示例,说明如何以正确的方式真正看到新属性和重写属性,以便我可以理解,也许我的示例很糟糕。 / p>

谢谢。

1 个答案:

答案 0 :(得分:1)

无论您覆盖或隐藏Name属性,都有两个单独的属性使用该名称,并且您可以通过this.Namebase.Name访问子类中的两个实现。 / p>

要查看预期的行为,您应该直接打印出car.Name,您将看不到任何结果-它为空。 car的编译时类型为Car,因此不使用子类实现。解析为Car.Name,未设置。请注意,打印car2.Name会打印被覆盖的属性,正是因为该属性被覆盖。

那么为什么打印car.Name会为您提供空值,而在this.Name中打印CheckName却行不通?

CheckName被覆盖,因此将调用Minivan中的实现。现在,在该方法的上下文中,this的编译时间类型为Minivan,不是吗?因此,在这种情况下,this.Name指的是Name的子类实现,因此会打印Minivan