为什么调用基类方法而不是派生类方法?

时间:2012-11-13 15:25:43

标签: c# inheritance

期待“来自派生的你好”。但得到“基地的你好。”。

class Program
{
    interface IBase
    {
        void Method();
    }

    public class Base: IBase
    {
        public virtual void Method()
        {
            Console.WriteLine("Hello from the base.");
        }
    }

    public class Derived : Base
    {
        public virtual new void Method()
        {
            Console.WriteLine("Hello from the derived.");
        }
    }

    static void Main(string[] args)
    {
        IBase x = new Derived();
        x.Method();
    }
}

那么为什么不调用派生类的方法呢?更重要的是,如何在不将x转换为Derived类型的情况下调用派生类方法?

在我的实际应用中,IBase有几个其他相关方法,Derived只替换了IBase中的两个方法。

5 个答案:

答案 0 :(得分:9)

当您使用new修饰符时,您明确指出该方法不是该层次结构的虚拟分派链的一部分,因此在基类中使用相同名称调用该方法将不会导致重定向到孩子班。如果您使用override而不是new标记方法,那么您将看到您希望看到的虚拟调度。

您还需要从派生类的方法中删除virtual,因为您无法将override方法标记为virtual(它已经是)。

如果您真的不想覆盖该方法,那么在您的情况下,根本不使用继承可能更合适。您可能只想使用接口:

public interface IFoo
{
    void Foo();
}

public class A : IFoo
{
    public void Foo()
    {
        Console.WriteLine("I am A, hear me roar!");
    }
}

public class B : IFoo
{
    public void Foo()
    {
        Console.WriteLine("I am B, hear me roar!");
    }
}

private static void Main(string[] args)
{
    IFoo foo = new A();
    foo.Foo();

    foo = new B();
    foo.Foo();

    Console.WriteLine();
    Console.WriteLine("Press any key to exit . . .");
    Console.ReadKey(true);
}

答案 1 :(得分:3)

这是基本的polymorphism

对于您正在寻找的行为,您需要设置派生方法以覆盖继承的方法:

public class Derived : Base
{
    public override void Method()
    {
        Console.WriteLine("Hello from the derived.");
    }
}

答案 2 :(得分:2)

在您的子类中使用override关键字而不是virtual new

因此,您的代码应如下所示:

class Program
{
    interface IBase
    {
        void Method();
    }

    public class Base: IBase
    {
        public virtual void Method()
        {
            Console.WriteLine("Hello from the base.");
        }
    }

    public class Derived : Base
    {
        public override void Method() // The magic happens here!
        {
            Console.WriteLine("Hello from the derived.");
        }
    }

    static void Main(string[] args)
    {
        IBase x = new Derived();
        x.Method();
    }
}

正如here所述,new关键字用于隐藏父方法,而不是您正在寻找的方法。

答案 3 :(得分:1)

new关键字创建了一个新方法,并说隐藏了基本方法。但它只适用于派生类的使用者,因为基类代码对它没有任何了解。

override关键字会使用新的关键字覆盖基类实现。

class Program
{
    interface IBase
    {
        void Method();
    }

    public class Base: IBase
    {
        public virtual void Method()
        {
            Console.WriteLine("Hello from the base.");
        }
    }

    public class Derived : Base
    {
        // the next line was changed.
        public override void Method()
        {
            Console.WriteLine("Hello from the derived.");

            // note that if you want to call the original implementation, you do it like this:
            base.Method();
        }
    }

    static void Main(string[] args)
    {
        Base x = new Derived();
        x.Method();
    }
}

答案 4 :(得分:0)

Derved中的新方法仅存在于Derived实例中,它有效地隐藏了基本实现。

但IBase类型只知道Base的实现,所以它调用它。

要回答您的问题,请调用派生程序的实现:

Derived d = new Derived();
d.Method();
((IBase)d).Method();

//Prints:
//Hello from the derived.
//Hello from the base.