7

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

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中的两个方法。

4

5 回答 5

10

当您使用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);
}
于 2012-11-13T15:33:32.023 回答
3

这是工作中的基本多态性

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

public class Derived : Base
{
    public override void Method()
    {
        Console.WriteLine("Hello from the derived.");
    }
}
于 2012-11-13T15:28:57.330 回答
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();
    }
}

如此处所述,new关键字用于隐藏父方法,这不是您要查找的。

于 2012-11-13T15:27:06.867 回答
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();
    }
}
于 2012-11-13T15:32:27.573 回答
0

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

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

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

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

//Prints:
//Hello from the derived.
//Hello from the base.
于 2012-11-13T15:43:33.443 回答