这是一个面试问题。那么是否可以覆盖没有在父方法中指定虚拟的方法?
答案 0 :(得分:19)
他们可能希望您说“使用new
关键字隐藏该方法。”这在技术上不会覆盖该方法。如果你有
class Base
{
public void Bar() { Console.WriteLine("Base"); }
}
class Derived : Base
{
public new void Bar() { Console.WriteLine("Derived"); }
}
然后你写了
Derived derived = new Derived();
derived.Bar();
((Base)derived).Bar();
你会看到不同的结果。因此,使用基类的函数将获得基本方法的结果,使用派生类的函数将获得新方法的结果。
答案 1 :(得分:4)
从技术上讲,您无法覆盖该方法。不过,您可以使用new
关键字隐藏它:
class Foo
{
public void Bar() {}
}
class FooChild : Foo
{
new public void Bar() {}
}
问题是当你从基类调用Bar()
时(或者如果你将FooChild转换为Foo),它将执行基类的代码 - 而不是“新”代码。
答案 2 :(得分:1)
如果可以覆盖非虚拟公共方法,我们将拥有更强大的模拟框架。不,覆盖非虚拟成员是不可能的,只能使用new
keyword 隐藏。
答案 3 :(得分:1)
以下不是重写。此外,请永远不要这样做。但是,提供替代行为是一种“技巧”:
class Base
{
protected Action m_action;
public Base()
{
m_action = () => Console.WriteLine("Base Class");
}
public void NonVirtual()
{
m_action();
}
}
class Derived : Base
{
public Derived()
{
m_action = () => Console.WriteLine("Derived Class");
}
}
class Program
{
static void Main (string[] args)
{
Base baseClass = new Base();
Derived derivedClass = new Derived();
Base derivedAsBase = derivedClass;
Console.WriteLine("Calling Base:");
baseClass.NonVirtual();
Console.WriteLine("Calling Derived:");
derivedClass.NonVirtual();
Console.WriteLine("Calling Derived as Base:");
derivedAsBase.NonVirtual();
Console.ReadKey();
}
}
结果:
Calling Base:
Base Class
Calling Derived:
Derived Class
Calling Derived as Base:
Derived Class
编辑:虽然我说这是一个技巧,但它可以整理到战略模式或类似。
答案 4 :(得分:0)
不,这将是隐藏功能。
答案 5 :(得分:0)
当您通过类型T的编译时引用访问该方法时,“new”关键字可以隐藏基类中定义的方法,例如typeof(DerivedClass).IsAssignableFrom(typeof(T))。但是,你无法真正覆盖它。在编译时使用基类型的引用将始终调用基本方法,无论您在派生类的定义中执行什么操作。
如果我在面试中被问到这个问题,那就是我要说的。如果我问它,那就是我希望的答案。任何认为“新”与“覆盖”相同并且不以某种方式限定答案的人都不明白“虚拟”的含义或vtable的工作方式(概念上或机械上)。
答案 6 :(得分:0)
这样我们就可以使用新关键字。
using System;
class Example
{
static void Main()
{
Foo f = new Foo();
f.M();
Foo b = new Bar();
b.M();
}
}
class Foo
{
public void M()
{
Console.WriteLine("Foo.M");
}
}
class Bar : Foo
{
public new void M()
{
Console.WriteLine("Bar.M");
}
}