【问题标题】:what is "public new virtual void Method()" mean?“public new virtual void Method()”是什么意思?
【发布时间】:2012-05-02 14:33:51
【问题描述】:

什么时候使用新的虚拟关键词来装饰方法?感情是什么?就像定义一个接口,并添加一个类来继承接口。而是使用新的virtual来实现接口方法。

 interface IPrinter
{
    void Print();
}

 public class PrinterOne : IPrinter
{
    public void Print() 
    {
        Console.WriteLine("PrinterOne.");
    }
}

public class PrinterTwo : PrinterOne
{
    public new virtual void Print()
    {
        Console.WriteLine("PrinterTwo.");
    }
}

public class PrinterThree : PrinterTwo
{
    public override void Print()
    {
        Console.WriteLine("PrinterThree.");
    }
}

public class PrinterFour : PrinterThree
{
    public override void Print()
    {
        Console.WriteLine("PrinterFour.");
    }
}

 static void Main(string[] args)
    {
        IPrinter iprinter = new PrinterFour();
        iprinter.Print();//the output is PrinterOne? why???
        Console.ReadLine();
    }

【问题讨论】:

标签: c#


【解决方案1】:

newvirtual 是两个(大部分)不相关的关键字。

new 表示它隐藏了基方法。
virtual 允许子类覆盖它。

通过接口调用方法会导致调用基方法,因为基方法不是virtual,并且派生类没有显式地重新实现接口(这会导致方法被重新映射) )

【讨论】:

    【解决方案2】:

    new 这样使用的关键字是成员隐藏。

    我从未见过它与virtual 关键字一起使用,请注意。它只是允许从PrinterTwo 派生到override 的类型实现Print 方法。

    以这种方式使用的new 关键字允许类型隐藏基类型的成员,但前提是您使用的是该类型本身的变量。

    例如,如果您要这样做:

    PrinterOne one = new PrinterTwo();
    one.Print();
    

    不会调用PrinterTwo 中的方法,因为它不是继承链的一部分。

    至于你什么时候会这样做......当你真的,真的需要出于一些我想不出的奇怪原因(也许是反思?)并且你不能编辑 PrinterOne 中的代码时。

    就我个人而言,我永远不会这样做。

    至于为什么输出是一台打印机...调用IPrinter.Print 将调用它所定义的类型(在这种情况下为PrinterOne),这将使您回到我上面关于new 的示例关键字被忽略,除非您与具有它的类型交谈。

    基本上,使用IPrinter 类似于在我上面的小示例中使用PrinterOne

    为解决问题,将PrinterOne方法设为virtual,并彻底去掉new virtualPrinterTwo中的使用。

    【讨论】:

      【解决方案3】:

      新修饰符

      http://msdn.microsoft.com/en-us/library/435f1dw2.aspx

      当用作修饰符时,new 关键字显式隐藏从基类继承的成员。

      这意味着该方法不会覆盖虚拟基类方法,但在派生类的实例上调用时仍具有优先权。也就是说,新方法只影响派生类的一个变量,不影响基类。

      虚拟修饰符

      http://msdn.microsoft.com/en-us/library/9fkccyh4.aspx

      virtual 关键字用于修改方法、属性、索引器或事件声明,并允许在派生类中对其进行覆盖。

      这意味着可以在派生类中重写该方法。当您在基类变量上调用虚拟方法时,该变量包含已覆盖虚拟方法的派生类的实例,将调用派生类实现。这与 new 关键字的行为相反。

      【讨论】:

        【解决方案4】:

        这称为方法隐藏。当您需要为无法覆盖的方法提供自己的实现时,您可以使用它。因为PrinterOne.Print 不是虚方法,所以不能被覆盖。相反,new 关键字用于创建隐藏原始方法的相同方法签名。将改为使用新方法。向此添加 virtual 关键字,允许您的新方法被派生类覆盖。

        只有在通过定义容器(例如PrintTwo)调用它时才会调用隐藏原始的新方法。通过接口调用它调用原始方法。请注意,该方法从未被删除或替换,因此通过直接访问接口,原始实现仍然存在。

        【讨论】:

          猜你喜欢
          • 2010-10-24
          • 2015-05-30
          • 2011-01-24
          • 1970-01-01
          • 2019-11-23
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多