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 the XCorolla. 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 for Accelerate() 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() and Break(). 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.
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.
Enjoy abstraction.
No comments :
Post a Comment