50

假设我有一个如下定义的接口:

public interface IFunctionality
{
    void Method();       
}

我为一个抽象类实现了这个接口,如下所示:

public abstract class AbstractFunctionality: IFunctionality
{
    public void Method()
    {
        Console.WriteLine("Abstract stuff" + "\n");
    }       
}

我再次有一个从抽象类继承的具体类,如下所示:

public class ConcreteFunctionality: AbstractFunctionality
{
    public void Method()
    {
        Console.WriteLine("Concrete stuff" + "\n");
    }
}

现在我有以下代码,

ConcreteFunctionality mostDerived = new ConcreteFunctionality();
AbstractFunctionality baseInst = mostDerived;
IFunctionality interfaceInst = mostDerived;
mostDerived.Method();
baseInst.Method();
interfaceInst.Method();

执行这些东西后我得到的输出如下。

Concrete stuff
Abstract stuff
Abstract stuff

但是我一直期望输出在所有三种情况下都是“具体的东西”,因为我在这里所做的是将 的引用分配给和 类型的ConcreteFunctionality变量。AbstractFunctionalityIFunctionality

内部发生了什么。请澄清。

4

3 回答 3

73

这里:

public class ConreteFunctionality:AbstractFunctionality
{
    public void Method()
    {
        Console.WriteLine("Concrete stuff" + "\n");
    }
}

...您没有覆盖现有方法。您正在创建一种隐藏现有方法的方法。(如果你真的想要这种行为,你也应该得到一个警告,建议使用修饰符。)接口是在 中实现的,所以接口映射表引用了该类中的方法。newAbstractFunctionality

现在如果你重新实现接口:

public class ConcreteFunctionality : AbstractFunctionality, IFunctionality

...然后接口映射将引用方法ConcreteFunctionality,您将获得通过接口调用的预期行为(即您的第三次调用),但您仍然会在AbstractFunctionality第二次调用中获得实现。

将方法设置为AbstractFunctionalityvirtual 并在ConcreteFunctionality. 这样,它将ConcreteFunctionality在所有情况下使用实现。

于 2013-01-25T07:05:26.033 回答
30

您需要将类定义为:

public abstract class AbstractFunctionality:IFunctionality
{
    public virtual void Method()
    {
        Console.WriteLine("Abstract stuff" + "\n");
    }       
}

public class ConreteFunctionality:AbstractFunctionality
{
    public override void Method()
    {
        Console.WriteLine("Concrete stuff" + "\n");
    }
}

由于您没有在 ConreteFunctionality 中覆盖 Method(),因此运行时环境执行与 AbstractFunctionality 对象关联的 Method(),因为它不能在此处应用动态多态性。引入virtual并使override运行时环境在子类中执行被覆盖的方法。

于 2013-01-25T07:05:04.743 回答
14

您缺少virtual关键字override。没有这个,您将无法获得虚拟功能。

您可以将MethodAbstractFunctionality 标记为virtual并将Methodin标记ConreteFunctionalityoverride。正如 mihirj 所展示的那样。

解决的类似问题 -为什么 C# 接口方法没有声明为抽象或虚拟的?

于 2013-01-25T07:04:10.110 回答