C#接口继承到抽象类

Vik*_*ram 50 c# oop abstract-class interface concrete

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

public interface IFunctionality
{
    void Method();       
}
Run Code Online (Sandbox Code Playgroud)

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

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

我还有一个具体的类,它继承自抽象类,如下所示:

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

现在我有以下代码,

ConcreteFunctionality mostDerived = new ConcreteFunctionality();
AbstractFunctionality baseInst = mostDerived;
IFunctionality interfaceInst = mostDerived;
mostDerived.Method();
baseInst.Method();
interfaceInst.Method();
Run Code Online (Sandbox Code Playgroud)

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

Concrete stuff
Abstract stuff
Abstract stuff
Run Code Online (Sandbox Code Playgroud)

但是我一直期望输出在所有三种情况下都是"混凝土东西",因为我在这里做的是分配ConcreteFunctionality类型AbstractFunctionality和变量的引用IFunctionality.

内部发生了什么.请澄清一下.

Jon*_*eet 74

这里:

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

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

现在,如果您重新实现界面:

public class ConcreteFunctionality : AbstractFunctionality, IFunctionality
Run Code Online (Sandbox Code Playgroud)

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

它通常更清晰,更保持理智,可以在AbstractFunctionality虚拟中创建方法,并覆盖它ConcreteFunctionality.这样它将ConcreteFunctionality在所有情况下使用实现.


mih*_*irj 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");
    }
}
Run Code Online (Sandbox Code Playgroud)

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

  • 很好的答案; 但我会介绍术语"隐藏",它描述了OP的原始代码,并注意隐藏没有"new"关键字的方法会导致编译器警告. (2认同)

Kar*_*k T 14

这是因为丢失virtualoverride关键字.没有这个,你就不会得到虚函数.

您可以Method在AbstractFunctionality中virtual标记为,并将Methodin 标记ConreteFunctionalityoverride.正如mihirj所示.

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