我应该将属性声明为接口还是基类(当它们同时实现时)

本文关键字:实现 基类 声明 属性 接口 我应该 | 更新日期: 2023-09-27 18:26:23

我有一个类以类似的方式使用一组属性(为了简洁起见,示例中只显示了两个)。一般行为是在基类上定义的,而特定行为是在特定接口中定义的

问题是:如果我将它们声明为基类,我必须将它们强制转换为接口来调用接口方法。现在,如果我将它们声明为接口,那么当我想调用基方法时,就必须将它们强制转换为基类。

在这里使用接口时,我的目标是提高可测试性(稍后使用依赖注入),并培养"按接口编程"的习惯,但我无法决定哪种方式是最好的,甚至无法决定整个原理是否良好。

public class Conductor
{
    // These properties inherit from base class
    // and implement one specific interface each:
    // declared as interface:
    IPlotterHelper  _plotter_helper = new PlotterHelper();
    // declared as base class:
    Helper _file_writer_helper = new FileWriterHelper();

    // When using handlers defined in specific interfaces:
    // have to cast this:
    this.NewFrame   += ((IPlotterHelper)_file_writer_helper).ProcessFrame();
    // but not this:
    this.NewSamples += _plotter_helper.ProcessSamples();

    // While when using handlers from the base class
    // have to cast this to the base class (since it is an interface):
    this.CommandSent += ((Helper)_plotter_helper).RunCommand;
    // but not this:
    this.CommandSent += _file_writer_helper.RunCommand;
}

internal class FileWriterHelper : Helper, IFileWriterHelper
{
    IFileWriterHelper.ProcessFrame()
    {
        // ...
    }
    // ...
}
internal class PlotterHelper : Helper, IPlotterHelper
{
    IPlotterHelper.ProcessSamples ()
    {
        ///
    }
    // ...
}
internal class Helper
{
    internal void RunCommand()
    {
        // ...
    }
}

我应该将属性声明为接口还是基类(当它们同时实现时)

当我面临在接口中具有默认行为的愿望时,我通常会考虑使用具有受保护的助手方法和一组抽象接口方法的抽象基类,或者使用"接口"方法的默认实现。即使我只从一个具体的实现开始,情况也可能是这样。

许多人将抽象类和接口视为实现选项的同一大类。

抽象类的问题是单一继承,所以只有当抽象类真的要成为类层次结构(即使是浅层次结构)的基础时,我们才应该使用它。接口可以用来用共同的行为装饰类(来自不同层次结构)。

对于测试,我看不出用接口伪造和用抽象类伪造有多大区别,但这可能取决于您的测试基础设施。

在这种情况下,我会使用一个抽象类,而忽略接口(除非它已经存在,在这种情况中,你没有任何选择)。

很难准确地看到你想做什么,但这似乎是一个更合适的设计:

public class Conductor
{
    private IPlotterHelper _plotter_helper = new PlotterHelper();
    private IFileWriterHelper _file_writer_helper = new FileWriterHelper();
    public void Conduct()
    {
        _file_writer_helper.ProcessFrame();
        _file_writer_helper.RunCommand();
        _plotter_helper.ProcessSamples();
        _plotter_helper.RunCommand();
    }
}
internal interface IHelper
{
    void RunCommand();
}
internal interface IFileWriterHelper : IHelper
{
    void ProcessFrame();
}
internal interface IPlotterHelper : IHelper
{
    void ProcessSamples();
}

internal class FileWriterHelper : Helper, IFileWriterHelper
{
    public void ProcessFrame()
    {
    }
}
internal class PlotterHelper : Helper, IPlotterHelper
{
    public void ProcessSamples()
    {
    }
}
internal class Helper : IHelper
{
    public void RunCommand()
    {
    }
}

接口和抽象类有着相同的目的:提供抽象。使抽象连贯,如果基类有公共成员,请确保它们也在接口上。

但是,为什么我需要的抽象类或接口-对。去掉基类或接口-您可能并不真的需要两者。我会放弃基础课。