SOLID 原则:接口与抽象 类

SOLID Principles : interfaces vs. abstract classes

我有一个特殊的边缘情况,我不确定是使用接口还是抽象 class。最初我的设计使用抽象 class,其中方法实现为 protected internal abstract void

这很有用,因为我希望这些方法可以从我的程序集中调用,但只能通过我的程序集外部的继承来使用。

我遇到的问题是,并非抽象 class 的所有衍生物都需要实现该功能,所以基本上我最终得到的是空方法体。

这是我想到使用接口的地方,这意味着我可以通过接口实现所需的功能,但这意味着方法需要 public,并且如上所述,我只希望方法通过继承可用。

使用抽象的例子class:

abstract class Dependency
{
    protected internal abstract void DoThis();
    protected internal abstract void DoThat();
}

sealed class DerivedDependency : Dependency
{
    protected override void DoThis()
    {
        // implementation...
    }

    protected override void DoThat()
    {
        // not required...
    }
}

使用接口的示例:

abstract class Dependency
{
    // whilst this is now empty, it is still required to provide a type hierarchy!
}

interface IDoThis
{
    void DoThis();
}

interface IDoThat
{
    void DoThat();
}

sealed class DerivedDependency : Dependency, IDoThis
{
    public virtual void DoThis()
    {
        // I only need this functionality. I don't need to DoThat();
    }
}

所以我想知道真正更好的是什么。两者都提供了我想要的功能,但我似乎不能两者兼得。

我是否只是忍受了第 3 方可能实现的空方法体,却没有意识到它们并不意味着要实现,或者,我是否只实现了所需的功能,但冒着通过实例化暴露功能的风险?

提到solid,你缺少的是接口隔离原则,你应该使用两个接口,一个用于内部消费者(标记为内部的方法),另一个用于外部消费者。

所以我不会选择抽象 class 也不会选择接口,而是选择两个(或更多)接口。

我可能找到了一个看起来效果不错的解决方案,但我希望社区能就此是否遵守或违反 SOLID 原则发表意见:

interface IDoThis
{
    void DoThis();
}

class Dependency : IDoThis
{
    protected internal virtual void DoThis()
    {
        // impl.
    }

    void IDoThis.DoThis()
    {
        this.DoThis();
    }
}

IDoThis idt = new Dependency();
idt.DoThis() // calls into the protected method.

这允许我通过接口 (ISP) 分离功能,在程序集中公开访问它,并在外部程序集中覆盖它 (OCP)