何时使用新的虚拟关键词来装饰方法?感情是什么?就像定义一个接口一样,并添加一个类来继承接口。但是使用新的虚拟来实现接口方法。
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();
}
答案 0 :(得分:11)
new
和virtual
是两个(大多数)无关的关键字。
new
表示它会影响基本方法
virtual
允许子类覆盖它。
通过接口调用方法会导致调用基本方法,因为基本方法不是virtual
,并且派生类没有显式重新实现接口(这将导致重新生成方法) -mapped)
答案 1 :(得分:10)
像这样使用的new
关键字隐藏了成员。
我从未见过它与virtual
关键字一起使用,请注意。它只是允许从PrinterTwo
到override
Print
方法实现派生的类型。
以这种方式使用的new
关键字允许类型隐藏基类型的成员,但前提是您使用的是类型本身的变量。
例如,如果你这样做:
PrinterOne one = new PrinterTwo();
one.Print();
不调用PrinterTwo
中的方法,因为它不是继承链的一部分。
至于你何时会这样做...当你真的,真的需要一些奇怪的原因,我想不到(反射可能?),你不能编辑PrinterOne
中的代码。 / p>
就个人而言,我不会这样做。
至于输出为打印机的原因...调用IPrinter.Print
会调用它所定义的类型(在这种情况下为PrinterOne
),这会让你回到我上面的例子中new
关键字被忽略,除非您与具有该功能的类型进行对话。
基本上,使用IPrinter
类似于在上面的小例子中使用PrinterOne
。
要解决此问题,请使用PrinterOne
方法virtual
并完全删除new virtual
中PrinterTwo
的使用。
答案 2 :(得分:4)
http://msdn.microsoft.com/en-us/library/435f1dw2.aspx
当用作修饰符时,new关键字显式隐藏从基类继承的成员。
这意味着该方法不会覆盖虚拟基类方法,但在派生类的实例上调用时仍然优先。换句话说,new方法只影响派生类的变量,而不影响基类。
http://msdn.microsoft.com/en-us/library/9fkccyh4.aspx
virtual关键字用于修改方法,属性,索引器或事件声明,并允许在派生类中重写它。
这意味着可以在派生类中覆盖该方法。当您在基类变量上调用虚方法时,该变量包含已覆盖虚方法的派生类的实例,则调用派生类实现。这与新关键字的行为相反。
答案 3 :(得分:1)
这称为方法隐藏。当您需要为无法覆盖的方法提供自己的实现时,可以使用此方法。由于PrinterOne.Print
不是虚方法,因此无法覆盖它。相反,new
关键字用于创建隐藏原始方法的相同方法签名。将使用新方法。向此添加virtual
关键字,可以通过派生类来覆盖新方法。
只有通过定义容器(例如PrintTwo
)调用它时,才会调用隐藏原始方法的新方法。通过接口调用它调用原始方法。请注意,该方法从未被删除或替换,因此通过直接访问界面仍然存在原始实现。