如何在不使用父类中的“虚拟”的情况下覆盖子类中的方法

时间:2010-09-03 02:14:27

标签: c# language-features

这是一个面试问题。那么是否可以覆盖没有在父方法中指定虚拟的方法?

7 个答案:

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