Abstract Class vs Interface – When to use which

In this article, I will discuss on Abstract Class vs Interface and the design decisions about when to use abstract class and when to use interface. This topic is covered at the last section of this article. But before that, let us understand the basics of what an abstract class and interface is, what are the similarities and differences between them. I will address this topic from a .NET background (on .NET Core 3.1 at the time of writing this article), however this concept is generally same across other technologies like JAVA, only the code constructs are different across different programming languages.

Abstract Class

Abstract class is a restricted class which has missing or incomplete implementation. It is intended only to be a base class of other classes and not instantiated on its own.

Features of Abstract Class

  • An abstract class cannot be instantiated
  • An abstract class cannot be sealed as sealed modifier prevents a class from being inherited & abstract modifier requires a class to be inherited
  • An abstract class can be declared without any abstract or non abstract methods i.e. and abstract class can be declared empty as public abstract class Base {}
  • Abstract methods cannot be defied in a non abstract class
  • It can contain any number of abstract and non abstract methods
  • All methods of an abstract class are private by default
  • When an abstract class is sub classed, the subclass usually provides implementations for all the abstract methods of its parent class. However, if it does not, then the subclass must also be declared abstract
  • Abstract methods are implemented by overriding them in the derived class
  • static or virtual modifiers cannot be used with abstract method declaration. Only non abstract methods can be declared as static or virtual
  • An abstract class cannot be static
  • If an abstract class contains only abstract methods and does not contain any non abstract method, it is same as an interface

Interface

An interface defines a contract to be implemented. Any class or struct which implements the contact (Interface) must provide implementation of the members defined in the interface.

Features of Interface

  • An interface is a completely abstract class i.e. an interface only contains abstract methods and properties. However, beginning with C# 8.0, an interface may define default implementation for its members
  • Methods of an interface are implicitly abstract, so abstract modifier is not used with interface methods
  •  Methods of an interface are implicitly public, so no access modifier even public can be used interface methods
  • Interface methods cannot be declared as static, however static fields are now permitted

Following example code snippet below shows sample implementation of abstract classes and interfaces. This is self-explanatory & I am not explaining each & every line of the following code.

using System;

namespace AsbtractClassVsInterface
{
    public abstract class Base
    {
        public void Method1()
        {
            Console.WriteLine("Method 1.");
        }
        public virtual void Method2()
        {
            Console.WriteLine("Method 2 in abstract class.");
        }
        public abstract void Method3();

        interface IInterfaceInAbstractClass
        {
            void IInterfaceMethodToImplementInAbstractClass();
        }
    }

    public interface IInterface1
    {
        static int x = 5; 
        static int Ctr
        {
            get
            {
                return x;
            }
            set
            {
                x += 2;
            }
        }

        int Ctr1 
        {
            get;set;
        }
        void IMethod1();
        void IMethod2()
        {
            Console.WriteLine("IMethod2");
        }
    }
    public class Derived1 : Base, IInterface1
    {

        private static int a;
        public override void Method2()
        {
            Console.WriteLine("Method 2 in derived class.");
        }
        
        public override void Method3()
        {
            Console.WriteLine("Method 3 from base class.");
        }

        public void Method4()
        {
            Console.WriteLine("Method 4 in derived class.");
        }

        public void IMethod1()
        {
            Console.WriteLine("IMethod1."); 
        }

        public void IMethod2()
        {
            Console.WriteLine("IMethod2 implemented in derived class.");
        }

        public void InterfaceMethodToImplementInAbstractClass()
        {
            Console.WriteLine("Interface Defined in Abstract Class whose method is Implemented in Derived Class.");
        }

        public int Ctr1 
        {
            get 
            {
                return a;
            }
            set
            {
                a += 1;
            }
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            Derived1 objDerived1 = new Derived1();

            objDerived1.Method1();
            objDerived1.Method2();
            objDerived1.Method3();
            objDerived1.Method4();
            
            objDerived1.IMethod1();
            objDerived1.IMethod2();
            objDerived1.InterfaceMethodToImplementInAbstractClass();

            IInterface1 objIInterface1 = new Derived1();
            objIInterface1.IMethod1();
            objIInterface1.IMethod2();

            IInterface1.Ctr = 8;
            Console.WriteLine(IInterface1.Ctr);

            objIInterface1.Ctr1 = 4;
            Console.WriteLine(objIInterface1.Ctr1);

            Console.ReadLine();
        }
    }
}

Following image shows the above sample console app’s output.

 abstract-class-vs-interface-sample-program-output

Abstract Class vs Interface – Sample console program output

Next, we will discuss on Abstract Class vs Interface and list down which one to choose when

When to use Abstract Class

  1. Abstract classes are used for implementing common functionality across closely related classes
  2. Abstract classes are used if there are plans to support future expansion of the product
  3. Abstract classes are used for designing large functional units
  4. Abstract classes provide less design flexibility
  5. Abstract classes are used to design class libraries which will be widely distributed or reused
  6. Abstract classes can not be used to introduce polymorphic behavior in the product
  7. Eg: System.IO.Stream abstract class (provided by .NET Framework) and System.IO.FileStream, System.IO.MemoryStream and many other Stream classes implements this Stream base class which contains the common functionality needed by various Streams like FileStream, MemoryStream etc. which clearly supports point (1) mentioned above

Note:

As the common functionality is duplicated across several classes, it should be moved in a base class & other classes can inherit from this abstract base class. If you create the base class as a concrete class & not an abstract class, then the base class can be instantiated directly. Since our Product does not have any feature like the base class & has only features for the derived classes, it would be wrong to instantiate the base class directly. Also, since the base class may have functionality (as virtual or abstract methods) that can be provided by derived classes only, it should not be allowed to instantiate the base class directly. Hence, the base class is defined abstract.

However, if you need the capability of instantiating the base class directly, you will create the base class as a regular non abstract base class and would inherit the base class like you do in normal inheritance. Finally, you would create an abstract class when you want to move the common functionality of multiple related classes into a single base class and you do not want the base class to be instantiated.

When to use Interface

  1. Interfaces are used for implementing common functionality across unrelated classes
  2. Interfaces are not a good choice for future expansion of the product as you will need to extend the interface & create a new one
  3. Interfaces are used for designing small concise bits of functionality
  4. Interfaces provide more design flexibility because they can be implemented by any class regardless of its type hierarchy
  5. Interfaces are used to design stand alone projects which can be changed at will rather than being widely distributed or reused
  6. Interfaces can be used to introduce polymorphic behavior in the product
  7. Eg:  IDisposable is an interface (provided by .NET Framework) that allows types to support disposability independent of any other inheritance hierarchy in which they want to participate. This clearly supports point (1) mentioned above – Interfaces are used for implementing common functionality across unrelated classes

This concludes the article – Abstract Class vs Interface – When to use which. I hope you liked this article.

Please comment and highight more differences on Abstract Class vs Interface which have not been mentioned in this article and also on design decisions on when to use which.

If you have any comments, questions or suggestions, please post them in the comments section below this article. I will try to respond at my earliest or somebody else reading the article and your comment will try to respond.

2 thoughts on “Abstract Class vs Interface – When to use which

Leave a comment