从基类调用子类的新方法

时间:2010-03-02 10:14:22

标签: c# methods new-operator invoke base-class

我有一些像这样的课程

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            A a = new C();

            a.method();
            Console.ReadLine();
        }
    }

    public class A
    {
        public virtual void method()
        {
            Console.WriteLine("METHOD FROM A");
        }
    }

    public class B : A { }

    public class C : B
    {
        public override void method()
        {
            Console.WriteLine("METHOD FROM C");
        }
    }
}

它工作正常,打印“METHOD FROM C”

BUT

如果我有这样的情况

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            A a = new C();

            a.method();
            Console.ReadLine();
        }
    }

    public class A
    {
        public void method()
        {
            Console.WriteLine("METHOD FROM A");
        }
    }

    public class B : A { }

    public class C : B
    {
        public new void method()
        {
            Console.WriteLine("METHOD FROM C");
        }
    }
}

打印“METHOD FROM A”。如果没有采用带有覆盖的强制转换或更改方法声明,我如何获得第一个示例的相同行为?

3 个答案:

答案 0 :(得分:11)

你不能 - 这种行为上的差异是使用虚拟/覆盖的全部要点。

当您使用“new”声明方法时,您说“我知道我隐藏具有相同签名的方法而不是覆盖它;我不希望多态行为。”

同样,当你声明一个没有指定“virtual”的方法时,你会说“我不希望子类能够覆盖这个方法。”

你为什么要这样做?你真的只是试图覆盖一个尚未声明为虚拟的方法吗?如果是这样的话,那就没有办法了 - 而且有充分的理由。如果作者没有设计具有多态性的类,那么如果能够覆盖该方法,它可能很容易破解。

当然,如果您声明变量属于子类的类型,如下所示:

C c = new C();
c.method();

然后调用新声明的方法。

答案 1 :(得分:2)

像乔恩说的那样避免它。但是

static void Main(string[] args)
    {
        A a = new C();

        (a as C).method();

        Console.ReadLine();
    }

答案 2 :(得分:1)

您可以使用动态关键字调用此方法。

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            dynamic a = new C();

            a.method();
            Console.ReadLine();
        }
    }

    public class A
    {
        public void method()
        {
            Console.WriteLine("METHOD FROM A");
        }
    }

    public class B : A { }

    public class C : B
    {
        public new void method()
        {
            Console.WriteLine("METHOD FROM C");
        }
    }
}