One of the basic questions which all of us need to go through when designing a module for our application is, whether to use an abstract class or an interface or a concrete class. In the below article, I am trying to explain this.
What is an abstract class and when do we use it?
Abstract class is a class which can't be initiated, which means they are considered as incomplete classes. Because they are incomplete classes, they can be called directly or can’t be instantiated.
Then, why do we even need these?
If you want to design an application/module where you have some standard/common functionality, which you would like to share in all the child classes; or you want the derived classes to be free to use and develop the other methods (declared as abstract in parent class), you need to create an abstract class.
We need to create an abstract class as a base class because it will transmit its default feature and create a derived class from this abstract base class performing a similar type of function.
So, the abstract class allows us to define a standard behavior, but also provides us a feature to override it if we want to.
Abstract class shares IS A relation with its child class. For example, Car IS A Vehicle, Truck IS A Vehicle (Here, Car and Truck are considered as child classes while Vehicle is a base abstract class.)
Similarly, Fulltime IS A Employee, Part-time IS A Employee etc. (Fulltime and Part Time are the derived classes and Employee is a base abstract class).
In both the above-given examples - Vehicle and Employee classes - we have some basic properties or methods which will be available in their derived class.
Like - All employees will need to have EmployeeID, Salary, ManagerID etc. Similarly, all Vehicles should have engines, brakes etc.
So now, the next question that comes into our mind is why do we create them abstract, when we could have created them as concrete classes? The reason is, since these classes are providing a template or common functionality to their derived classes while keeping themselves incomplete, we do not want anyone to directly use them, which means we do not want anyone to create an object of them and start using them because these are the base classes which contain a basic framework or skeleton or template for their child classes.
Example - .NET Framework provides many abstract classes like Stream, but does not allow us to create an object of these while it provides its subclasses like FileStream, MemoryStream, PrintqueueStream, which get inherited from the Stream class and are available for use.
An abstract class can be enhanced anytime in the future, without having any side effect to any client or class using them. An abstract class provides versioning while interface does not provide versioning.
Whenever we have a scenario where we need to create multiple related classes having IS A relationship, then we need to put all common features or methods in an abstract class and let all other classes derive from this base class. Common features of Abstract class can be further enhanced in the future and the changes or enhanced features will be available in derived classes without any issue.
Also, use an abstract class, when you are creating a class library, which can be enhanced in the future and be distributed or reused to clients. Also when you need to define a common base default behavior, which can be shared among derived classes.
One more important point to keep in mind is, abstract class can't be instantiated. That means it can't have a public constructor. However, it is perfectly valid for an abstract class to have internal or protected constructor for its own use.
What is Interface and when to use it
Just a quick definition of Interface - Interface can't have any implementation of any method. All methods in interfaces are just declared, which means interface can only have the signature of the methods. It can't have definition of any method. And also, Interface supports multiple inheritance, which abstract class does not support.
The main drawback of interfaces is that they are much less flexible than classes when it comes to allowing for evolution of APIs. After you ship an interface, the set of its members is fixed forever and interface is frozen. Any additions or alternation to the interface would break existing types that implement the interface.
Besides these drawbacks, Interfaces are those rules that can't be avoided and give the idea of what is to be done, but not how it will be done. It's a contract or a promise the class has to make while implementing an interface.
Whenever we need to develop any service by (WCF) which can be used by multiple clients following multiple different protocols, then we need to have common rules/contracts which needs to be followed by the client. Interfaces are used to create those rules or principle in service oriented architecture(SOA).
Interfaces are also used to create loosely coupled components. Meaning whenever we have a scenario where two classes are dependent on each other, it is not a good practice to create an object of one class in another class directly. If we do it, any future change in any class which is being used, will break the other class. So, Interface breaks the tight coupling and instead of one class creating the object of another class directly, we should let the classes use interface and pass the interface as dependency.
(I will cover dependency injection in my next article😊)
When deciding to use abstract class and when to use interface, we can consider few rules:
If you are creating a class library containing a common base functionality and will be widely distributed, then use abstract class, because abstract class supports versioning and can be enhanced any time without breaking the existing client or existing applications which are using it.
When creating a standalone application, which supports polymorphism, use interface if you want your child classes to implement multiple unrelated functionalities. In short, for multiple inheritance use interfaces.
Whenever you need to develop a service following SOA architecture, then use interface to create a contract. That contract will be used and shared between the service and consumer. Any SOA principle works on those common rules which are defined in the interface.