覆盖/新方法

时间:2013-12-16 20:50:11

标签: c# inheritance polymorphism virtual-functions

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

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

  2. 我教科书中关于new方法关键字的说明是:

  3.   

    有时您可能希望创建自己的基类中存在的方法实现。 Line类通过声明它来完成此操作   拥有print()方法。 Line print()方法隐藏了DrawingObject   print()方法。效果是父print()方法不会   叫,除非我们做一些特别的事情以确保它被调用。   注意Line类print()方法中的new修饰符。这使得   这个方法隐藏了DrawingObject类的print()方法和   明确说明你不想要多态的意图   发生。如果没有new修饰符,编译器将产生警告   引起你的注意。

    如果有什么影响?

    1. 基类方法是虚拟的,派生的是新的吗?
    2. 基类方法不是虚拟的,派生的是新的吗?
    3. 如果我没有在派生类
    4. 中使用new关键字,会发生什么
    5. 如果方法在基类中不是虚拟的,那么多态如何发生?
    6. 为什么“如果没有new修饰符,编译器会产生警告”?
    7. 问题请参考以下代码。

      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.");
          }
      }
      

4 个答案:

答案 0 :(得分:2)

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

    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(),都不应该有所区别。

答案 1 :(得分:1)

virtual (C# Reference)

  

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

您可以从Knowing When to Use Override and New Keywords (C# Programming Guide)

回答大多数其他问题

答案 2 :(得分:0)

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

  1. 如果您有派生类型的变量 - 将调用新方法。如果你有基类型的变量(但实际上有派生类型),将调用基类的虚方法。
  2. 同样。
  3. 如果用覆盖标记它,你将获得经典的多态性。
  4. 方法应该是虚拟的基类来使用多态。
  5. 如果您无意中创建了一个隐藏基类版本的新方法,则会对您发出警告。您应该使用new明确表达您的意图,并确保它不是错误。

答案 3 :(得分:0)

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


  

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