为接口中的抽象方法提供实现

问题描述 投票:0回答:1

是否可以通过从为该方法提供默认实现的接口派生来重写方法实现?如果不是,我应该如何重构我的代码以避免对接口实现的显式方法调用?

以下是我的项目中类结构的概述:

interface IInputProcessor
{
    public ProcessInputsResult ProcessInputs(Item[] inputs);
}

abstract class MachineComponent : IInputProcessor
{
    public abstract ProcessInputsResult ProcessInputs(Item[] inputs);
}

interface IComponentContainer<T> where T : MachineComponent
{
    public T[] Components { get; }
}

class MachineSystem : MachineComponent, IComponentContainer<MachineComponent>
{
    public MachineComponent[] Components { get; }
}

我的目标是在

ProcessInputs
接口内提供
IComponentContainer
的实现,因为所有组件容器都必须处理其每个组件的输入,并且其实现可以在派生类之间共享。

为了实现这一点,我尝试在

ProcessInputs
内部为
IComponentContainer
创建一个默认方法实现,如下所示:

interface IComponentContainer<T> : IInputProcessor where T : MachineComponent
{
    public T[] Components { get; }

    ProcessInputsResult IInputProcessor.ProcessInputs(Item[] inputs)
    {
        ...
    }
}

请注意,我还如何使

IComponentContainer
派生自
IInputProcessor
,因为所有组件容器都必须处理其所有组件的输入。

我希望这个新定义意味着

MachineSystem
(既是
MachineComponent
又是
IComponentContainer<MachineComponent>
)不需要指定
MachineComponent.ProcessInputs
的实现,因为这是在
IComponentContainer
接口中给出的.

事实并非如此,我必须明确地将方法引用到接口中给出的实现,如下所示:

class MachineSystem : MachineComponent, IComponentContainer<MachineComponent>
{
    ...

    public override ProcessInputsResult ProcessInputs(Item[] inputs) =>
        ((IComponentContainer<MachineComponent>)this).ProcessInputs(inputs);
}

我认为这违背了在接口中提供默认实现的目的,因为派生类必须指定它们想要使用。

这个问题有好的解决方案吗,还是应该改变代码结构?

c# inheritance methods interface c#-9.0
1个回答
0
投票

我认为这违背了提供默认值的目的 接口中的实现作为派生类必须指定 他们想要使用的。

派生(或接口实现)类不需要指定任何内容,如果它们没有抽象类让它们这样做。

你定义了这样一个类

abstract class MachineComponent : IInputProcessor
{
    public abstract ProcessInputsResult ProcessInputs(Item[] inputs);
}

现在所有派生类(如果不是抽象类本身)都需要重写该方法,从而提供一个实现,该实现将同时隐藏/优先于接口的默认接口实现。

这实际上甚至会阻止您的解决方法发挥作用

public override ProcessInputsResult ProcessInputs(Item[] inputs) =>
    ((IComponentContainer<MachineComponent>)this).ProcessInputs(inputs);

此强制转换方法调用编译为以下 IL:

callvirt instance class ProcessInputsResult IInputProcessor::ProcessInputs(class Item[])

因此,我们从

IInputProcessor::ProcessInputs
最具体/派生的实现中对
IInputProcessor::ProcessInputs
进行虚拟调用。换句话说,我们有无限的递归。

这使我们认识到,我们不能在应该重写的方法中重用默认接口实现,就像在类继承中的虚拟重写方法中调用

base.BaseClassMethod
一样。

我的目标是在内部提供 ProcessInputs 的实现 IComponentContainer 接口,因为所有组件容器都必须 处理每个组件的输入,以及实现 因为这可以在派生类之间共享。

我认为通过将

IComponentContainer<T>
作为抽象类,你可以解决大部分(如果不是全部)问题:

abstract class ComponentContainer<T> : MachineComponent where T : MachineComponent {
    public T[] Components { get; }
    public override ProcessInputsResult ProcessInputs(Item[] inputs) {
       // implementation - will server for interface dispatch too
    }
}

class MachineSystem : ComponentContainer<MachineComponent> {
    // no need for anything here...we inherit from abstract class
}
© www.soinside.com 2019 - 2024. All rights reserved.