【问题标题】:Override/new methods覆盖/新方法
【发布时间】:2014-01-04 10:00:21
【问题描述】:

我是 C# 新手(来自 C++)

  1. 我可以将方法声明为 virtual 和 override 吗?(在 C++ 中,该方法在基类和派生类中也可以是虚拟的)

  2. 我的课本中关于new方法关键字的解释说:

有时您可能希望创建自己的基类中存在的方法的实现。 Line 类通过声明其 自己的 print() 方法。 Line print() 方法隐藏了 DrawingObject 打印()方法。效果是Parent print() 方法不会 调用,除非我们做一些特殊的事情来确保它被调用。 注意 Line 类 print() 方法上的 new 修饰符。这使 此方法隐藏 DrawingObject 类的 print() 方法和 明确说明您不希望多态性的意图 发生。如果没有 new 修饰符,编译器将产生警告 提醒您注意这一点。

如果它有什么影响?

  1. 基类方法是虚的,派生的是新的?
  2. 基类方法不是虚的,派生的是新的?
  3. 如果我不对派生类中的方法使用 new 关键字会发生什么
  4. 如果方法在基类中不是虚方法,多态性如何发生?
  5. 为什么“没有 new 修饰符,编译器会产生警告”?

问题参考以下代码。

using System;

public class DrawingObject
{
    public virtual void Draw()
    {
        Console.WriteLine("I'm just a generic drawing object.");
    }
    public void print()
    {
        Console.WriteLine("I'm a Parent Class.");
    }
}
public class Line : DrawingObject
{
    public override void Draw()
    {
        Console.WriteLine("I'm a Line.");
    }
    public new void print()
    {
        base.print();
        Console.WriteLine("I'm a Child Class.");
    }
}

public class Circle : DrawingObject
{
    public override void Draw()
    {
        Console.WriteLine("I'm a Circle.");
    }
}

public class Square : DrawingObject
{
    public override void Draw()
    {
        Console.WriteLine("I'm a Square.");
    }
}

【问题讨论】:

  • 这不是 C++ 问题,所以我删除了那个标签。
  • 对于问题1-3,只需创建这样一个程序并尝试一下。你可以很容易地观察结果。你甚至已经有了代码,所以,只需执行你拥有的代码。
  • 至于方法隐藏与覆盖你可以看这篇文章:stackoverflow.com/questions/1170158/c-sharp-and-method-hiding

标签: c# inheritance polymorphism virtual-functions


【解决方案1】:
  1. 如果实例成员在基类中声明为virtual,那么它将继续 在派生类中保留virtual,直到它不会被标记 作为sealed。
  2. 避免使用 new 关键字,因为它会破坏多态性(请参阅您使用 Draw 方法的示例 - 它应该被标记为虚拟)。

多态性破坏示例:

public class Base
{
    public void Method()
    {
        Console.WriteLine("Base.Method()");
    }
}

public class Derived : Base
{
    public new void Method()
    {
        Console.WriteLine("Derived.Method()");
    }
}

Derived obj = new Derived();
obj.Method(); // Will output "Derived.Method()"
((Base)obj).Method() // Will output "Base.Method()"

当您使用类层次结构时,这不是您通常所期望的。无论您是从基类还是从派生类调用 Method(),都应该没有区别。

【讨论】:

    【解决方案2】:

    virtual (C# Reference)

    您不能将 virtual 修饰符与 static、abstract、private 或 override 修饰符一起使用。

    您的大部分其他问题都可以通过Knowing When to Use Override and New Keywords (C# Programming Guide) 回答

    【讨论】:

      【解决方案3】:

      派生类中的new关键字被称为“遮蔽”基类的方法,本质上它隐藏了基类的方法实现。如果您省略 new 关键字,您看到的警告消息是编译器告诉您应该明确声明您打算使用 new 语法隐藏/隐藏该方法。在语法中使用new 关键字会使任何阅读您的代码的人都清楚您隐藏了一个基本实现。


      注意:这只是一个警告,因为通过在派生类中实现非虚拟方法,您正在隐藏/隐藏基类的实现。编译器只是告诉你要成为一个好公民,并通知正在阅读你代码的其他人。

      【讨论】:

        【解决方案4】:

        是的,您可以使用virtual 关键字标记方法,然后在派生类中使用override 覆盖它。

        1. 如果您有派生类型的变量 - 将调用新方法。如果您有基类型的变量(但其中确实包含派生类型),则将调用基类中的虚拟方法。
        2. 一样。
        3. 如果你用 override 标记它,你会得到经典的多态性。
        4. 方法应该是虚拟它的基类才能使用多态性。
        5. 如果您偶尔无意地创建了一个隐藏基类版本的新方法,这是对您的警告。您应该使用new 明确表达您的意图,并确保这不是错误。

        【讨论】:

          猜你喜欢
          • 2019-05-04
          • 2010-09-06
          • 1970-01-01
          • 2018-06-21
          • 1970-01-01
          • 2020-06-14
          • 2015-12-25
          • 2016-03-06
          • 2018-03-27
          相关资源
          最近更新 更多