Search code examples
c#oopmethodsinterfaceaccess-modifiers

Using protected methods in interfaces


I wonder whether it is a good idea to use protected members in the interface to create a contract for the derived classes internal logic.

On the one hand, it breaks the encapsulation and leads to possible YAGNI violation (since some of the derived classes might not really need that member), LSP violations (if the derived classes do not fully implement it), tighter coupling etc.

On the other hand, I really want to clearly declare the necessity of some internal logic implementation (which is supposed to be common among all derived classes).

For instance, I want to use the builder pattern in my project. Imagine, I have an interface like this:

internal interface IReportBuilder
{
    IReportBuilder BuildHeader();
    IReportBuilder BuildMainBody();
    IReportBuilder BuildFooter();
    AbstractReport GetReport();
}

The implementation might be:

internal class WorkReportBuilder : IReportBuilder
{
    private AbstractReport _report = new WorkReport(); 

    public IReportBuilder BuildHeader()
    {
        //building the header
        return this;
    }

    public IReportBuilder BuildMainBody()
    {
        //building the main body
        return this;
    }

    public IReportBuilder BuildFooter()
    {
        //building the footer
        return this;
    }

    public AbstractReport GetReport()
    {
        var result = _report;
        Reset();

        return result;
    }

    private void Reset()
    {
        _report = new WorkReport();
    }
}

Should I just add a method protected void Reset(); to the interface to make sure that the derived classes do implement resetting?


Solution

  • Since interfaces are expected to reflect the behavior of objects that implement it, using protected members inside it ruins the whole sense of having an interface.

    Regarding your example, you might consider to create an abstract class ReportBuilder which implements the IReportBuilder interface. Speaking of abstract classes, they can definitely have some internal logic (in your case, representing the Reset method). So that your WorkReportBuilder derives from the abstract class with private/protected logic you needed.