Introduction
The purpose of this article is to demystify the
misconceptions about Interfaces and to explore some of its uses which beginners
may find mysterious.
Interfaces
What is the difference between an abstract class and an
interface? Why should we go for an interface when we have abstract class that
performs the similar action? These questions are quite common and have been
asked in almost all the developer job interviews. Interfaces are for providing
a good level of abstraction. Like that, the answers by the beginners for those
questions are also in an abstract manner J
People answer the first and foremost thing which they think
the only actual answer. It is not possible to do multiple inheritance (both in
case of Java and .NET). Yes, but why you need to inherit multiple classes to a
class. If it is a frequently used stuff, the technology you work for should
have it supported right? The technologies like .NET and Java are not supporting
for many reasons. (http://blogs.msdn.com/b/csharpfaq/archive/2004/03/07/why-doesn-t-c-support-multiple-inheritance.aspx)
Okay, we can achieve multiple inheritance for an extreme by
using multiple interface inheritance. Is that the only reason interface are
added to the languages? No! Interfaces are primarily for abstracting the
object’s core implementation from the consumers. Why should we have an abstract
class then? When we have some common concrete code, that has to be shared among
the derived classes, the abstract class would be the right choice.
Object creation will of course come with a cost. For
example, in .NET, when we create an object, the object’s memory will be
allocated in the heap and the pointer for that object will be put on the thread
stack. Along with the actual object, all the parent, grandparent and great
grandparent objects will be created. So, if we use an abstract class which has
no concrete method in it, when we create an object for the derived class,
objects for both the parent and the child will be created.
For example,
BaseClass b = new DerivedClass();
DerivedClass d = new DerivedClass();
Both the above examples will be creating object for
DerivedClass
which in turn create a base class object. While using the instance
b, the abstracted version of DerivedClass
will only be accessible. While using
the instance d, the full version (both the overridden methods of the BaseClass
and the concrete methods of DerivedClass
) of DerivedClass
will be accessible.
Okay, one more basic question. From whom we are protecting the derived class
elements? Does someone will corrupt/hack the object? Not all the time! It
depends on the problem domain. The primary objective of abstracting the object
from the consumer is to decouple the consumer and the object. So, when some of
the internal behaviour in the object gets changed, the object’s consumer
doesn’t require changing their code as well.
Interfaces will also be providing the similar level of the
abstraction like the abstract class. But, unlike the abstract class, there will
not be a separate object created for interface instance upon using it. And of
course, we can do multiple interface inheritance and can use the required
interface to create the object in the consumer to achieve various levels of
abstraction.
That’s all? No! Interface shall also be used to group the
methods/properties with respect to those purposes and the way those should be
available to the clients (who make use of the interface to access the object).
And hence, the consumer shall not worry about the other behaviour the object
has. The object’s state will also not be changed by mistaken access and the
client code will be perfectly decoupled.
Consider the following example:
public interface IEmployee
{
string ID;
string Name { get; set; }
}
public interface IPayrollMember : IEmployee
{
double Salary { get; set; }
}
internal class Employee : IEmployee, IPayrollMember
{
public string ID
{
get;
set;
}
public string Name
{
get;
set;
}
public double Salary
{
get;
set;
}
}
Consider the application has a class defined for Employee to
manipulate employee details. The class is being used by many applications in
the same company. As we have two interfaces IEmployee
and IPayrollMember
, for
the module used by gate security, IEmployee
interface shall alone be exposed
and for the payroll department, the interface IPayrollMember
shall be exposed
(which has IEmployee
members too with the help of interface inheritance). So,
at any cost, the developer who develops the gate security application will not
be aware of what else an employee object might contain and hence his code will
be perfectly decoupled from other members the Employee class has. So, any
changes happens inside Employee class, the security module will remain
unaffected.
Wait! How can you say that the security module will not be
aware of the whole Employee class? What if the developer creates the employee
object directly like:
Employee e =new Employee();
Yes, and that’s why we made Employee class as internal. So,
we should also expose another class that helps the consumers to create the
required object.
public class EmployeeFactory
{
public IEmployee GetEmployee(string id)
{
return CreateEmployeeObject(id);
}
public IPayrollMember GetPayrollMember(string id)
{
return CreateEmployeeObject(id);
}
private Employee CreateEmployeeObject(string id)
{
return new Employee(id);
}
}
The gate security app
developer shall make use of GetEmployee
method to get the employee details and
the payroll person shall make use of GetPayrollMember
to get the required
object.
Disclaimer:
The intention of this article is not to cover everything
about interface but to demystify some of the misconceptions. Factory pattern
used in this article is just to show how the other behaviour of the class shall
be hidden. The object creational logic can even be in some other better way!