Interface vs Abstract class. The classic confusion
One of the mostly asked question in OOP is about choosing between
an Interface and an Abstract class. These two look pretty similar and it
appears as if one could be used instead of another. So, which one should be
most appropriate to use to lay out class designs?
These two things are similar, and both talk about abstraction,
rather than concrete implementation. Both concepts are interpreted and
inherited from the real world. But, there is a small difference in their
purpose.
Interface talks about "What" functionality a
particular kind of object should have, and, it doesn't care
about exactly "How" these functionality should be
implemented by the actual objects of those kind.
For example, let us consider a Vehicle object. A
vehicle could be of any brand in the world. But, what are the core
functionality of a vehicle? What would you expect from a vehicle while you try
to purchase one? The very basic things you would expect would be:
It must start
It must run
It must break
It must accelerate
It must stop
So, how would you identify these "very basic" features
for any vehicle in the OOP?
You already know it. You create an interface and put these
functionality as some method signatures without definition. That is:
interface IVehicle
{
void Start();
void Run();
void Accelerate();
void Break();
void Stop();
}
So, this basically describes what are the basic functionality that
a vehicle (Any vehicle made by any manufacturer) should have. Now, how these
functionality are going to be implemented? Well, It completely depends on the
manufacturers. One particular kind of vehicle might start using a Remote
control, and another might start with a Key. One might accelerate via an auto
gear and another might accelerate via a manual gear. In OOP, these particular
implementations are defined by the classes which implements the interface. The
interface knows nothing about these concrete implementation and it is quite
happy about that.
On the other hand, an "Abstract class" also talks about
"What" functionality a particular kind of object should have,
but, it may also talk about "How" a particular functionality
is implemented.
Need an example? Here you go
Toyota makes cars and of course all of its cars have the very
basic functionality that a vehicle should have. So, each car obviously
implements the IVehicle interface. For now, let us assume
Toyota makes cars based upon only two models, the Camry and
theXCorolla. So, while laying out the Camry and XCorolla classes,
they implement the IVehicle classes as follows:
class Camry : IVehicle
{
public void Start()
{
//Starts with a Remote control
}
public void Run()
{
//Runs via a 2000CC Toyota
engine
}
public void Accelerate()
{
//Accelerates
via an Auto gear
}
public void Break()
{
//Breaks
via an hydrolic break
}
public void Stop()
{
//Stops with a key, or a remote
control
}
}
class XCorolla: IVehicle
{
public void Start()
{
//Starts with a Key
}
public void Run()
{
//Runs via a 1500CC Toyota
engine
}
public void Accelerate()
{
//Accelerates
via an Auto gear
}
public void Break()
{
//Breaks
via an hydrolic break
}
public void Stop()
{
//Stops with a key
}
}
Looks pretty good, but, wait a minute. The Camry and
the XCorolla class both seem to be having a same
implementation forAccelerate() and Break(), though,
these two classes implement the other three functionality Start(), Run() and Stop() in
different ways. So, as these two classes have a same implementation for the Accelerate() and Break() functionality,
why shouldn't these be re-used?
The IVehicle interface could of-course be used in
this case, but, it is not allowing to re-use the same functionality Accelerate() andBreak().
So, how about using an Abstract class?
Let us help Toyota to improve their programs a bit, by creating an
abstract class Car, that contains the common functional
implementation for Accelerate and Break.
abstract class Car : IVehicle
{
public abstract void Start();
public abstract void Run();
public abstract void Stop();
public void Accelerate()
{
//Accelerates
via an Auto gear
}
public void Break()
{
//Breaks
via an hydrolic break
}
}
As you see, the abstract class Car contains
concrete implementations of Accelerate() and Break() function
(They have method definition), but, abstract implementation of Start(), Run() and Stop() (They
don't have method definition). Why two concrete implementations? Because, these
two functions are the same for both Camry and the XCorolla classes.
Why two abstract implementations? Because, these two function's concrete
implementation are not same for Camry and XCorolla classes.
So now, the Camry and the XCorolla classes
would be re-defined as follows:
class Camry : Car
{
public void Start()
{
//Starts with a Remote control
}
public void Run()
{
//Runs via a 2000CC Toyota
engine
}
public void Stop()
{
//Stops with a key, or a remote
control
}
}
class XCorolla: Car
{
public void Start()
{
//Starts with a Key
}
public void Run()
{
//Runs via a 1500CC Toyota
engine
}
public void Stop()
{
//Stops with a key
}
}
This time, the Camry and the XCorolla classes
don't include the definition of Break() and Accelerate(),
because, they inherit those from the abstract Car class.
To summarize, the purpose of abstract classes is not only to
define abstraction between classes, but also to define concrete definition of
functions which are common across the concrete implementation classes.
Interfaces allow us to identify (Not implement) the functionality a particular
kind of object where Abstract classes allows to both identify and implement the
functionality across the objects, that increases re-usability and code
manageability and allows to build better systems.
However, it doesn't mean that, all interfaces should be replaced with Abstract classes. Try to use Abstract classes wherever possible and wherever applicable, where use of Abstract classes allows you to increase code manageability and reuse.
However, it doesn't mean that, all interfaces should be replaced with Abstract classes. Try to use Abstract classes wherever possible and wherever applicable, where use of Abstract classes allows you to increase code manageability and reuse.