我应该将属性声明为Interfaces还是Base类(当它们同时实现时)?

时间:2015-12-11 12:54:29

标签: c# inheritance interface casting

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

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

我在这里使用接口的目的是提高可测试性(使用依赖注入,以后),并培养“编程到界面”的习惯,但我无法确定哪种方式最好,或者即使整个基本原理是好在第一位。

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()
    {
        // ...
    }
}

3 个答案:

答案 0 :(得分:3)

当我面临在接口中拥有默认行为的愿望时,我通常会考虑使用带有受保护助手方法的抽象基类和一组抽象接口方法或“接口”方法的默认实现。即使我只从一个具体的实现开始,情况也许如此。

许多人认为抽象类和接口属于同一类广泛的实现选项。

抽象类的问题是单继承,所以我们应该只使用抽象类,如果它真的是类层次结构的基础(甚至是浅层)。接口可用于装饰具有共同行为的类(来自不同的层次结构)。

对于测试,我认为使用接口伪装和使用抽象类伪装之间没有太大区别 - 但这可能取决于您的测试基础架构。

在这种情况下,我会使用一个抽象类并忘记界面(除非它已经存在,在这种情况下你无论如何都没有任何选择)。

答案 1 :(得分:1)

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

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()
    {
    }
}

答案 2 :(得分:0)

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

但是,为什么我需要抽象类或接口? - 对。摆脱基类或接口 - 你可能并不真正需要。我放弃了基类。