Search code examples
c#.netinterfaceabstract-class

Choosing allowed methods from Abstract Class


I have an abstract class with methods with logic. Then i have childs but not all childs can have all methods from the abstract class. I have been thinking of a design pattern that allows me to keep the logic instead of using interfaces but can't think of anyhting other then using a static class with methods. But it would make my code very sloppy.

Another way of formulating my question is: How do i use interfaces with logic in them...

public abstract class Company
{
    public virtual void Dowork1()
    {
        //logic
    }

    public virtual void Dowork2()
    {
        //logic
    }

    public virtual void Dowork3()
    {
        //logic
    }
}

public class ItCompany : Company
{
    //DoWork2 NOT callable
}

public class ManagementCompany : Company
{
    //DoWork1 NOT callable
}

Solution

  • A pillar of object oriented programming is Liskov substitution principle. In practical terms this means that any implementation of Company need to implement all the methods. I.e. one implementation of a company should be possible to substitute for any other.

    You seem to be concerned about implementation inheritance, i.e. allow any of the implementations to reuse the same logic without the need to reimplement it. This can be problematic since it couples the base class to the derived classes. However, you should be able to do what you describe by making the implementations protected.

    public abstract class Company
    {
        protected virtual void DoworkImpl1()
        {
            //logic
        }
    
        protected virtual void DoworkImpl2()
        {
            //logic
        }
    
        protected virtual void DoworkImpl3()
        {
            //logic
        }
    }
    

    This lets each implementation define what parts they want to expose:

    public class ItCompany : Company
    {
        public void Dowork1() => DoworkImpl1();
        public void Dowork3() => DoworkImpl3();
    }
    

    You may also add different interfaces for each type of company if you want to, as shown in other answers. However, if Company does not expose any public methods, you cannot really do anything with a object of the base type, except check what specific type it is, and this is often indicative of a problem in the class design. I would recommend reading Eric Lipperts article on Wizards and Warriors for some perspective.

    A possible replacement is to move logic to static methods, for example using extension methods or default interface methods:

    public static class CompanyHelpers{
        public static void Dowork1(this ICompany company){
             // Logic
        }
    }
    

    This can be very useful with well designed interfaces that expose a minimal set of functions, and provides most extra functionality via extension methods. See LINQ for an example. But it may or may not be applicable in your specific situation.