【问题标题】:understanding override and new property理解覆盖和新属性
【发布时间】:2018-08-12 23:47:14
【问题描述】:
    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它会将方法隐藏在派生类中, 如果您使用覆盖,则新实现将被计算在内,并且它是使用的那个,但我不明白为什么这不会发生 使用 properties ,根据我的理解,我应该期望 car 中的 base.Name 应该打印“Minivan”(因为隐藏了 Minivan 类中的派生名称),而 this.Name 将为空。 (据我所知)

此外,当我在 VS car.Name 中检查对象 car 时,即使它打印了 "Minivan" ,但这种行为对我来说似乎真的很奇怪。 谁能给我解释示例代码中发生的事情,或者任何人都可以提出一个更好的例子来说明如何真正看到新的和覆盖的属性以正确的方式工作,以便我理解,也许我的例子很糟糕。

提前致谢。

【问题讨论】:

  • 该类实际上具有 两个 具有相同Name 的属性。你设置其中之一。你没有设置另一个。因此它是null。那有意义吗?哪个具体部分让您感到困惑。
  • 当你覆盖它时,你扩展了现有的,当newing它时,你隐藏它。在VB.Net 中称为Shadowing。也许他们选择这个名字是为了提供一个更好的主意。
  • 我的问题是,在属性中使用 new 和 override 有什么区别。好的 Jimi 我隐藏了它,但为什么我的实例车打印 this.Name 而它没有隐藏,它假设打印 base.Name 如果是我在 mi Minivan 类中隐藏 Name 的情况,为什么我有相同的行为?
  • whats the difference between using new and override in properties. 你想要一个属性(即存储一个值)吗?使用override。你想要两个(即存储两个不同的值)吗?使用new。请记住,使用new几乎总是是错误的想法。默认使用override请注意,在许多情况下,您实际上并不需要 两者 - 只需将其声明在基类中并根据需要从继承类中读取/写入即可。
  • Car 的实例是什么? Car carMinivan 类型,Car car2ConveribleCar 类型,这里。 根据我的理解,汽车中的 base.Name 应该打印“Minivan”(因为在 Minivan 类中隐藏了派生名称),而 this.Name 将为空。没有。谁在隐瞒谁?

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


【解决方案1】:

无论您覆盖或隐藏Name 属性,都会有2 个具有该名称的单独属性,您可以通过this.Namebase.Name 访问子类中的这两个实现。

要查看您的预期行为,您可能应该直接打印出car.Name,您会看到什么都没有出现——它是空的。 car 是编译时类型Car,所以不使用子类实现。它解析为未设置的Car.Name。请注意,打印 car2.Name 会打印被覆盖的属性,正是因为该属性已被覆盖。

那么为什么打印car.Name 会给你null,而在CheckName 中打印this.Name 不起作用?

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

【讨论】:

  • Okey,所以在第二段中,据我了解,我正在向 Mininvan 隐藏 Car.Name,这就是为什么我在 car.Name 中得到一个空值,因为我使用的是 Minivan.Name,这样可以吗? .那么为什么在 car2.CheckName 中我在 Base.Name 中得到 null 如果覆盖它的假设以覆盖父类中的值,这里我的理解很清楚或者我错过了什么?
  • @Oscar car.Name 为空,因为您在 Car 类中访问 Name。只设置了Minivan.Name。所以是的,你是对的。关于您评论的后半部分,覆盖确实使car2.Name 解析为Convertible.Name,但在表达式base.Name 中,您正在访问Car.Name。覆盖属性并不意味着您失去对它的所有访问权限。您仍然可以通过base.Name 访问基类实现。这就是base 的意思。
  • 谢谢@Sweeper,我几乎得到了你在每条评论中所说的一切,但仍然(对不起,如果我没有得到它)​​那么在 ConvertibleCar 和中用 override 和 new 标记 Car.Name 和小型货车,因为我所看到的以及您向我解释的行为是相同的,或者几乎是因为 car2.Name 确实具有“可转换”,这意味着我将 Car.Name 设置为与 car.Name 中发生的相反的情况,它为空,但为什么in car2.checkName() 在 Base.Name 中给出 null?,再次非常感谢,我只是想弄清楚这是如何工作的。
  • @Oscar car2.Name 不为空。 car.Name。这就是区别。执行checkName 时产生相同结果的原因是因为在checkName 内部,隐藏不再生效,因为this 的类型为Minivan。只有在父类变量 (Car) 中存储子类对象 (Minivan) 时,才能看到隐藏效果。然而,通过覆盖,变量的类型无关紧要。仅通过查看对象的类型来选择要调用的方法。
  • 我现在明白了区别,现在我的问题是,当我根据 VS 中的对象资源管理器设置 car2.Name="Convertible" 时,我在 Car.Name 中设置了这个属性,但这是因为我的对象具有的“可见性”是我的类型 Car 而不是 ConvertibleCar 的可见性,但是正在做的是在 ConvertibleCar.Name 中设置属性,这就是为什么在 Convertible Car base.Name 中为 null,这是正确的吗?再次提前感谢
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-07-19
  • 1970-01-01
  • 2018-11-08
  • 1970-01-01
相关资源
最近更新 更多