Archive for the ‘CodeProject’ Category

Prerequisite

Before reading this article, you should read the first and second part of this series.

Delegation

When a client object X requests some service from an object Y, then Y may decide to pass this request to another object Z instead of handling the request by itself. When this happens, we say that receiver object Y has delegated its operation to its delegate Z. This process is known as delegation and it’s a way of making object composition as powerful for reuse as inheritance.

Let us now consider an example from this famous book on design patterns. Suppose that we want to create a class which will generate a window.  The code for this class may look something like below –

/* We are using an interface so that all window drawing classes have a
 * common Object Interface (Remember the OOP principle 1 from first part? ) 
 */
public class Window
{
    // Various member variables
    public void drawWindow()
    {
        // Code to draw the window
    }

    // various other methods
}

This approach is a naive one. A better approach would be to create a Rectangle class which will contain the logic to generate a simple rectangle and then inherit this Window class from this rectangle and thereby including its functionality.

However, there is another approach. Instead of inheriting this Window class from Rectangle, we may delegate the responsibility from this class to another class called DrawRectangleShape like this –

public interface DrawWindow 
{
    public void draw(Window X);
}

public class DrawRectangleShape implements DrawWindow
{
    // various data and methods

    public void draw(Window X)
    {
        // logic to generate a rectangular-shaped window X
    }
}

public class Window
{
    DrawWindow windowDrawer;
    // Various member variables

    public Window()
    {
        /* It is OK to initialize this windowDrawer reference to a particular
         * object instance, but you should also provide setter method so that
         * this reference can be changed dynamically.
         */
        this.windowDrawer = new DrawRectangleShape();
    }

    public void setWindowDrawer(IDrawWindow windowDrawer)
    {
        this.windowDrawer = windowDrawer;
    }

    public void draw()
    {
        this.windowDrawer.draw(this)        // Pass self-reference to the delegate
    }

    public void redraw()
    {
        // destroys the current window, then regenerates it
    }

    // various other methods
}

Now if you look at the code you’ll see that the Window object is passing itself to the delegate so that the delegate can properly generate a rectangular window. This is always the case when the delegate requires a reference to the receiver.

Now why should we use delegation?

The main advantage of delegation is that it makes it easy to compose behaviors at run-time. Consider another implementation of the IDrawWindow interface –

public class DrawCircularShape implements DrawWindow
{
    // various data and methods

    public void draw(Window X)
    {
        // logic to generate a circular-shaped window X
    }
}

Now consider the following piece of code –

Window newWindow = new Window();
newWindow.draw();

DrawWindow newWindowDrawer = new DrawCircularShape();
newWindow.setWindowDrawer(newWindowDrawer);
newWindow.redraw();

The above piece of code first generates a rectangular-shaped window. After that, it replaces its default rectangular shape drawer with a circular shape drawer and then redraws itself. As a result, the window will become circular from rectangular at run-time!!!

So, using delegation you can change the behaviors of objects at run-time in this way. A lots of design patterns make use of this technique.

Unfortunately, delegation has some disadvantages too. Dynamic, highly parameterized software is typically harder to understand than more static software. If you delegation then you will have codes that changes behaviors at run-time. Understanding these varying behaviors may prove to be difficult. There are also some run-time inefficiency since you have to create new objects and transfer responsibilities to them, but this is negligible because most of the modern processors are pretty fast and because of the flexibility it brings to a software design.

So when using delegation, always make sure that it simplifies the design more than it complicates. Only then you will be able to leverage the true power of delegation.

Conclusion

At this point you should have a pretty good understanding of what design patterns are and what do they accomplish. You will find various other definitions on various books and on the web. I think you will now understand all of them 🙂 . Read them on your own. For the time being, I am going to include the definition of design patterns given by Christopher Alexander who first introduced the idea –

The elements of this language are entities called patterns. Each pattern describes a problem that occurs over and over again in our environment, and then describes the core of the solution to that problem, in such a way that you can use this solution a million times over, without ever doing it the same way twice.

I hope someone finds this series useful 🙂 .

Advertisements
Prerequisites

Before reading this article, you should read the first part of this series. In the following article, I may have used class and object interchangeably. Unless otherwise stated, they both mean the same thing.

Abstract Class VS Concrete Class

An abstract class is one which is generally declared using the keyword abstract and which has at least one method which doesn’t have a definition (or a body/implementation, whatever you say). Classes which aren’t declared using the abstract keyword is called Concrete Classes.

All the classes that I have given example of in the previous article are concrete classes.

Let us see an example of an abstract class –

public abstract class AnAbstractClass{
    protected string anAttribute;

    public void setAttribute(strint anAttribute){
        this.anAttribute = anAttribute;
    } 

    public string getAttribute(){
        return this.anAttribute;
    }

    public void anAbstractOperation();
}

The above class is an abstract class, since it is declared as abstract in its class definition. Abstract classes will defer some or all of its implementation to operations defined in subclasses; hence an abstract class cannot be instantiated. The operations that an abstract class declares but doesn’t implement are called Abstract Operations.

Now, why do we care ?

We do care about abstract classes because they play an important part in design patterns. An abstract class is one whose main purpose is to define a common interface for its subclasses (“subclass” will be explained shortly). They are generally used to define a Base Type to be used in the class hierarchy of a system.

Inheritance

In OOP, new classes can be defined in terms of existing classes. This mechanism is known as inheritance. When a new class is created in this way, we say that it is a subclass of the existing class from which it is  being inherited, and the existing class is called its parent class.

In the previous article of this series (link of which is given in the prerequisite section), I have shown an example of inheritance. Feel free to take a look at that example.

Objects that are instances of the subclass can contain all data defined by the subclass and its parent classes, and they’ll be able to perform all operations defined by this subclass and its parents.

But again, those who want to see another example, consider the following one –

// Example 1
public class Account{
    protected string accountNumber;
    protected double balance;

    public Account(){}

    public void setAccountNumber(string accountNumber){
        this.accountNumber = accountNumber;
    }

    public string getAccountNumber(){
        return this.accountNumber;
    }
}

public class InventoryAccount extends Account{
    protected string inventoryItemNumber;

    public InventoryAccount(){}

    public void setItemNumber(string itemNumber){
        this.inventoryItemNumber = itemNumber;
    }

    public string getItemNumber(){
        return this.inventoryItemNumber;
    }
}

In this example, we are creating a new class called InventoryAccount by inheriting it from Account class. As a result, all of the operations that Account class defines will be available in the InventoryAccount class. Here, InventoryAccount is a subclass of Account class, and Account class is a superclass of InventoryAccount.

Class Inheritance VS Interface Inheritance

“What the heck!? There are two types of inheritance?!”

Yes, that’s right. We use both of them on a daily basis, we just aren’t aware of the distinction. Class inheritance defines an object’s implementation in terms of another object’s implementation. In short, it’s simply a mechanism for code and representation sharing. The example that I’ve provided just above is an example of this type of inheritance.

Interface inheritance, sometimes known as subtyping, ensures that an object has a specific type of object interface which it obtains either from a programming language’s interface (let’s call it method interface just to distinguish itself from the Object Interface for now) or from an object.

“Huh? What did you just say? Aren’t both of these are the same thing then ?”

Nope, they are not. Look at the example I have provided. Here, InventoryAccountis inherited from Account class. So it also inherits both the methods that Account class provides, along with their implementation. This is an example of class inheritance – InventoryAccount is defined in terms of Account class’s implementation (along with its other methods, of course).

But, if I inherit InventoryAccount in the following way –

public class InventoryAccount extends Account{
    protected string inventoryItemNumber;

    public InventoryAccount(){}

    public void setAccountNumber(string accountNumber){        // Overriding Account's implementation
        this.accountNumber = accountNumber;
    }

    public string getAccountNumber(){                         // Overriding Account's implementation
        return this.accountNumber;
    }

    public void setItemNumber(string itemNumber){
        this.inventoryItemNumber = itemNumber;
    }

    public string getItemNumber(){
        return this.inventoryItemNumber;
    }
}

then I am only inheriting Account’s Object Interface, not their implementation. This is called interface inheritance.

Still not clear? Then comment back in!

Class inheritance is basically just a mechanism for extending an application’s functionality by reusing functionality in parent classes. It lets you define a new kind of object rapidly in terms of an old one. It lets you get new implementations almost for free, inhering most of what you need from existing classes. However, implementation reuse is only half the story. Inheritance’s ability to define families of objects with identical interfaces is also important.

Why? Because Dynamic Binding, and in turn, Polymorphism depends on it (“Huh? How?”).

When inheritance is used carefully (some will say properly), all classes derived from an abstract class will share its interface. This implies that a subclass merely adds or overrides operations and does not hide operations of the parent class. Consequently, all subclasses can then respond to the requests in the interface of this abstract class, making them all subtypes of the abstract class. As a result, all of these subclasses can be switched with one another in run-time, resulting in polymorphic behaviors.

There are two major benefits to manipulating objects solely in terms of the interface defined by abstract classes –

  • Clients (take a look at the definition of “client” from the previous article) remain unaware of the specific types of objects they use, as long as the objects adhere to the interface that clients expect.
  • Clients remain unaware of the classes that implement these objects. Clients only know about the abstract classes defining the interface.

Can you imagine the implication of the above two points ? You can’t ? Ok, fine, then let me help you.

Consider our Accounting example. Suppose that you are developing an accounting application which only handles Inventory Accounts and you have created only InventoryAccount class. Your code looks somewhat like below –

List<InventoryAccount> accounts = new ArrayList<InventoryAccount>();
accounts.Add(new InventoryAccount("Whatever initialization parameter is needed"));

.............. // Add another thousand class, do some manipulation, then save
ClassThatSavesAnAccountListToTheDatabase newClass = new ClassThatSavesAnAccountListToTheDatabase();
newClass.save(accounts);

Now after working hard for 3-4 months, your client (this client is a person 😉 ) comes to you and tells you, “Sooo sorry, I forgot to mention that this software will also manage our salary accounts. Could you do that for us, it would be a great help :D”, at that very moment you will be thinking, “Darn it, I am dead 😦 “.

Why?

Because to accommodate this change, you will have to declare a new account class called SalaryAccount, code for its business logic, persistence etc. You will also need to change the business logic in every place of your system, re-test it again thoroughly, and be sure that there will be hundreds of bugs this time in your system, all of which will be needed to be taken care of by you. In this scenario, we say that there is an implementation dependency between the subsystems of your application.

Instead of developing this way, if you would have declared an abstract class called Account and inherited InventoryAccount like the way I have shown in the inheritance example, and coded your application like this –

List<Account> accounts = new ArrayList<Account>();
accounts.Add(new InventoryAccount("Whatever initialization parameter is needed"));

.............. // Add another thousand class, do some manipulation, then save
ClassThatSavesAnAccountListToTheDatabase newClass = new ClassThatSavesAnAccountListToTheDatabase();
newClass.save(accounts);

then you could have just declared another class called SalaryAccount by extending your Account abstract class and it would have fitted nicely with your existing code. You will still need to change some part of your code, but believe me, the amount of change will be very, very less in this later case, and we say that implementation dependency in this case is kept to minimal.

So the problem arose because you have coded your application using a reference to a concrete type, rather than using am abstract type. All the clients of your InventoryAccount class were aware of this fact, and hence fitting in the new class proved to be difficult.

So, I hope now you can realize the benefits to manipulating objects solely in terms of the interface defined by abstract classes. This way of coding so greatly reduces implementation dependency between subsystems that it leads to the following principle of Reusable Object-Oriented design –

OOP Principle 1: Program to an Interface, not to an Concrete Implementation

What does this mean?  In short, this principle says that you should not declare variables to be instances of particular concrete classes. Instead, commit only to an interface defined by an abstract class or method interface.

Does design pattern help us to achieve this principle

What do you know, it does! Almost all of the design patterns make use of this principle and show you a way to use it in your application. So, we can say –

Design patterns help us to program to an interface, not to an concrete implementation, thereby reducing
implementation dependency as much as possible.

There you go. Another definition of what design patterns are 🙂 .

Reuse Mechanism in OOP

There are a lot of ways we can reuse existing code in an application, but the following two mechanisms are mostly used –

  • Class Inheritance
  • Object Composition

As we have learned before, class inheritance lets us define new implementation of one class in terms on another’s. Reuse by Subclassing in this way is often referred to as White-box reuse, because with this type of inheritance, the internals of parent classes are often visible to subclasses. Class inheritance is defined statically at compile-time and is straightforward to use, since it is supported directly by most of the OO languages. Class inheritance also makes it easier to modify the implementation being reused. When a subclass overrides some but not all of the operations, it can affect the operations it inherits as well, assuming the call the overridden operations.

But this type of reuse mechanism has some serious limitations. First, you cannot change the implementations inherited from parent classes at run-time, because inheritance is defined at compile-time, resulting in causing difficulties for polymorphism. Second, parent classes often define at least part of their subclasses’ physical representation. Because inheritance exposes a subclass to details of its parent’s implementation, it’s often said that Inheritance Breaks Encapsulation.

“What?! Did I hear you right?!”

Yes, you did. It may sound scary, but it’s true, because in this case the implementation of a subclass becomes so bound up with the implementation of its parent class that any change in the parent’s implementation will force the subclass to change. This is another form of Implementation Dependency.

Consider the following example –

public class Display{
    private string dataToDisplay;

    public Display(){}

    private void setDisplayData(string dataToDisplay){
        this.dataToDisplay = dataToDisplay
    }

    private string getDisplayData(){
        return this.dataToDisplay;
    }

    public void displayDataVertically(){
        // Code to display the data vertically
        .......
    }
}

public class LCDDisplay{

    public LCDDisplay(){}

    public void displayDataHorizontally(){
        // Code to display data horizontally
    }
}

In the above example, LCDDisplay is inheriting the displayDataVertically operation from its parent class, Display. If I change the logic of this operation in the Display class, it will also force the behavior of the LCDDisplay class to change, because this functionality of LCDDisplay class is defined in terms of the implementation that the Display class provides, resulting in the implementation dependency, and if the height of this inheritance tree keeps growing, you will really be in trouble if you ever need to change even a small part of your application.

This type of implementation dependencies can cause problems when you’re trying to reuse a subclass. Should any aspect of the inherited implementation not be appropriate for new problem domains, the parent class must be rewritten or replaced by something more appropriate. This dependency limits flexibility and ultimately reusability. One cure for this is to inherit from abstract classes, since they usually provide little or no implementation.

Object composition is an alternative to class inheritance. Here, new functionalities is obtained by assembling or composing objects to get more complex functionality. It requires that the objects being composed have well-defined object interfaces. This style of reuse is called Black-box reuse, because no internal details of objects are visible. Objects appear only as black boxes.

Let us look at the following example –

public class Account{
    protected string accountNumber;
    protected double balance;
    protected InterestRateCalculatorInterface RateCalculator;
    protected final double rate = 0.5;                        // Bad coding style, please don't follow it.
                                                              // I am using it just for the sake of this
                                                              // example.

    public Account(double initialBalance){
        this.balance = initialBalance;
    }

    public void setBalance(double initialBalance){
        this.balance = initialBalance;
    }

    public double getBalance(){
        return this.balance;
    }
    public void setAccountNumber(string accountNumber){
        this.accountNumber = accountNumber;
    }

    public string getAccountNumber(){
        return this.accountNumber;
    }

    public void setRateCalculator(InterestRateCalculatorInterface RateCalculator){
        this.RateCalculator= RateCalculator;
    } 

    public InterestRateCalculatorInterface getRateCalculator(){
        return this.RateCalculator;
    }

    public void calculateRateAndUpdateBalance(int numDays)
    {
        this.balance = this.RateCalculator.returnInterestRate(this.balance, numDays, this.rate);
    }
}

public interface InterestRateCalculatorInterface{               // Now that's what we've named method interface
                                                                // this series of articles.

    public double returnInterestRate(double baseValue, int numDays, int rate);
}

public class InterestCalculator implements InterestRateCalculatorInterface{
    public double returnInterestRate(double baseValue, int numDays, double rate){
        double finalRate = (double) ( baseValue + (baseValue * numDays * rate) );

        return finalRate;
    }
}

class SomeCertainClass{
    public static  void main(String[] args){
        Account newAccount = new Account(0.0);
        InterestRateCalculatorInterface RateCalculator = new InterestCalculator();    // Remember our
                                                                                  // OOP Principle 1?
        newAccount.setRateCalculator(RateCalculator);

        newAccount.calculateRateAndUpdateBalance(30);
        System.out.Print("The new balance is: " + newAccount.getBalance());
    }
}

In the above example, we are assigning an instance of an InterestCalculator object, which has the type InterestRateCalculator,  to the member variable of the Account object at run-time, which adds a new functionality in the Account class and enables it to calculate interest rate and update the current balance. This is an example of object composition, and we say that the Account object is being composed by an object which has the type InterestRateCalculatorInterface at run-time.

Object composition is defined dynamically at run-time through objects acquiring references to other objects, thus being more Polymorphism-friendly. It requires objects to respect each others’ interfaces, which in turn requires carefully designed interfaces that don’t stop you from using one object with many others. But there is a pay-off. Because objects are accessed solely through their interfaces, we don’t break encapsulation. Any object can be replaced at run-time by another as long as it has the same type. Moreover, because an object’s implementation will be written in terms of object interfaces, there are substantially fewer implementation dependencies. Favoring object composition over class inheritance helps you keep each class encapsulated and focused on one task. Your classes and class hierarchies will remain small and will be less likely to grow into unmanageable monsters. On the other hand, a design based on object composition will have more objects ( if fewer classes), and the system’s behavior will depend on their interrelationships instead of being defined in one class.

From the above discussion, we can see that object composition has very, very few bad effects compared to the class inheritance. This gives rise to our second OOP Principle –

OOP Principle 2 - Favor Object Composition over Class Inheritance

Ideally, Ideally, you shouldn’t have to create new components to achieve reuse. You should be able to get all the functionalities you need just by assembling existing components through object composition. But this is rarely the case, because the set of available components is never quite rich enough in practice. Reuse by inheritance makes it easier to make new components that can be composed with old ones. Inheritance and object composition thus work together. Nevertheless, statistics say that designers overuse inheritance as a reuse technique, and designs are made more reusable and simpler by depending more on object composition.

Does design pattern help us to achieve OOP Principle 2

Yes it does. There is a pattern called strategy which teaches us how to compose objects at run-time to get different behaviors out of a particular class. Almost all of the design patterns favor composition over inheritance. So, we can say –

Design patterns enable us to reuse our code in the most efficient way by favoring object composition
over class inheritance.

Enough for today. I am tired and hungry. I hope I can finish this introduction in the next article. Until then, good bye 🙂 .

Prerequisite

It will be better if you have a rough understanding of object oriented programming and its concepts like encapsulation, polymorphism and inheritance. If you don’t have those then this article may appear a little confusing. If it does then comment back in, I will try my best to explain. All of the example code that I provide here will follow Java syntax.

What are design patterns

From wikipedia

A design pattern in architecture and computer science is a formal way of documenting a solution to
a design problem in a particular field of expertise.

What do you understand from the above two lines ?

If you ask me, I will say – not a darn thing. This is the problem that occurs to all the beginners in design patterns. People and websites who teach these stuff seem to talk in a way that is very hard for the beginners to understand. Rather than pursuing these heavy definitions, let us learn what design patterns are by looking at their applications.

Do you know what are Objects

To simply put, an object is something that has –

  • data (or, you can say attributes/properties/states)
  • operations that operate on the data (they are also called methods)

Objects are used to perform some operations using their data. An object performs an operation when it receives a request from another object. The requesting object is said to be a client of the first object. You request an operation of an object by invoking one of its methods with appropriate arguments. In return, that operation performs some job for you and may return you a response.

Enough talk. Let’s see some code.

Before you create an object, you need to let the compiler know what data and operations will that object contain. You do this by declaring a class as follows –

public class Person{
    protected String name;    // Data

    public  person(){}    // Constructors, a special type of operation

    public String getName(){     // Operation
        return this.name;
    }

    public void setName(String name){
        /** 
         * Here EscapeString is another object whose
         * service is being requested by this Person
         * class. So Person is a client of EscapeString.
         */
        String escapedName = EscapeString.escape(name);
        this.name = escapedName;
    }
}

You can think of the class as a blue print for compilers which describes what data and operations will an object contain in it.

And now, to create an object, you use the following syntax –

Person aPerson = new Person();

Again I would like to point out that this article is not for those who are absolute beginner in object oriented programming . This article provides a different perspective of those concepts. You should acquire basic concepts from this fine article that Java’s official site provides.

Requests are the only way to get an object to execute an operation. Operations are the only way to change an object’s internal data. Because of these restrictions, the object’s internal state is said to be encapsulated.

Meet Encapsulation

Encapsulation means that the data that an object contains cannot be accessed directly from outside that object, and its representation is invisible from outside the object. It is a great way to develop a loosely coupled software components.

What the heck do the above two lines mean ?

It means that you cannot access the name property of the Person object directly. If you need to get that value then you will have to request it through the getName method. Doing it this way gives the designer of the object a lot of flexibility, i.e., he can change the name of the variable to myname and it still won’t cause any code to change outside this object. The designer can even choose to store the name value in a Java Map or in an array without much trouble.

Does design patten help us to maintain encapsulation

Yes, it does! There are a lots of design patterns that are targeted specifically for this purpose. One of them is Strategy Pattern. It helps us to encapsulate complex data structures, algorithms, changing behaviors into their own separate class and protect the rest of the system from any change that may occur in them. So, we can say –

Design patterns help us to maintain Encapsulation when we write an application in a true object oriented way

This is one of the most important uses of design patterns.

How should we determine what should be an object
  • You can write a problem statement, single out the nouns and verbs, and create corresponding classes and operations.
  • Or you can focus on the collaborations and responsibilities in your system.
  • Or you can model the real world and translate the objects found during analysis into design.

Do you understand anything from the above three points ?

If you don’t, then don’t worry. These are part of a broader topic known as system analysis and design, which I will cover later in the future.

What you would like to know whether or not design patterns help you to determine what should be an object in your system, and you will be glad to know that they do. There is a pattern called Facade which describes how to represent subsystems as objects. There is also another pattern known as Flyweight that describes how to support huge number of objects at the finest granularities.

So we can say –

Design patterns help us to decide what should be an object in our system.

This is another important use of design patterns.

Method signature, Object Interface, Types, Subtypes and Supertypes

Every operation declared by an object specifies the operation’s name, the objects it takes as parameters, and the operation’s return value. This is know as the operation’s signature. Don’t confuse it with method signature which doesn’t include the return type of a method.

Let us consider the Person object discussed earlier. The method signature of its getname operation is –

String getName()

The set of all signatures defined by an object’s operations is called the interface to the object (beware people, it’s not the same as our programming language’s interface  construct). There is one thing that you should be aware of. Some OOP languages allow us to declare methods that cannot be accessed from outside that object (i.e., in java using private, protected keywords). Those methods won’t be included in the object interface since you cannot request those operations to an object from outside that object.

If we consider the Person object, then its interface is –

{void setName(String name), String getName()}

An object’s interface characterizes the complete set of requests that can be sent to the object. Any request that matches a signature in the object’s interface may be sent to the object.

A type is a name used to denote a particular interface. We speak of an object as having the type X if it accepts all requests for the operations defined in the interface X. An object may have many types, and widely different objects can share a type.

As an example, we can say that the interface that our Person object defines is of type Person.

Interfaces can contain other interfaces as subsets. We say that a type is a subtype of another if its interface contains the interface of its supertype.

Let us consider an example. Suppose that I have a class called Man whose interface is as follows –

{void setName(String name), String getName(), void playCricket(), void playKabadi()}

This object’s interface contains all the method signatures that are defined in the Person object’s interface. So in this case we can say that Man is a subtype of Person, and Person is a supertype of Man. We can also say that this Man object’s interface inherits the Person’s object’s interface.

Why am I talking about these stuff?

Because interfaces are fundamental in object-oriented systems. Objects are known only through their interfaces. There is no way to know anything about an object or to ask it to do anything without going through its interface. An object’s interface says nothing about its implementation though. Different objects are free to implement requests differently. That means two objects having completely different implementations can have identical interfaces.

Let me clarify the last point with an example. Consider the following definition of the Man object –

public class Man extends Person{

    public Man(){}

    public String getName(){
        return EscapeString.escape(this.name);
    }
    public void setName(String name){
        this.name = name;
    }
    public void playCricket(){
        System.out.Print("I am playing cricket");
    }
    public void playKabadi(){
        System.out.Print("I am playing kabadi");
    }
 }

This example uses inheritance to make sure that the Man object has the Person object’s interface as its subtype. You can learn more about inheritance by reading the Sun Java’s article. All I will say is this – since we are inheriting Man class from Person class, then all of the methods that constitute its object interface will also be included in the Man class. The Man class is providing a different implementation to those methods by overriding definition/implementation of those methods. That’s all we care about for this article.

Those who find this example confusing, I would like to say to them that Object Interface and Java/C# language’s interface aren’t the same thing, though they have so much in common. Object interface is the collection of all signatures of all the methods that can be called from outside that object; where as an interface in C#/Java defines a collection of method signatures that some object can implement, thus including those signatures in its Object Interface. In this sense you can say that an interface construct in C#/Java defines an object interface, but it isn’t the only way. In those languages we can ensure that an object has a specific Object Interface by one of two ways –

  • By extending/inheriting another from another object. In this way the object’s Object Interface from which it is being inherited will be included in this object.
  • By declaring an interface, which is a collection of method signature, using the interface keyword that those languages provide and implementing that interface.

Probably now you will want to say that aren’t these two are the same thing? I will say, no, because an object that doesn’t implement any Programming Language’s interface still has an Object Interface, which is the collection of all the signatures of all those methods that can be called outside from this object.

Please think about this distinction thoroughly before moving on.

From our definition of interface, type and subtype, we can say that Man class also has Person as its type, because it accepts all the operations defined in the Person interface type.  It’s supertype is Person, and it’s a subtype of Person.

Now, look at the implementation of the getName and setName. They are completely different from the Person’s implementation, although they have common interface.

Since these objects have common interface, you can use one in place of another when you’re dealing with only that common interface. Let me clarify it with another example. Consider the following method of a certain class –

public String returnProcessedName(Person p)
{
    /** 
     * nameProcessor is a member variable of CertainClass
     * whose type is <em>Person</em>. You can use a setter
     * method for setting up appropriate name processor,
     * but hey, this is just an example!
     */
    this.nameProcessor = p;
    return this.nameProcessor.getName();
}

Now I can call this method like this –

Person newPerson = new Person();
CertainClass c = new CertainClass();

newPerson.setName("Stupid");
String processedName = c.returnProcessedName(newPerson);

Or like this –

Man newMan = new Man();
CertainClass c = new CertainClass();

newMan.setName("Stupid");
String processedName = c.returnProcessedName(newMan);

This code snippet is also valid. Why? Because both the Person and the Man object has a common interface, which we have named Person before. So you can use one object in place of another whenever you are dealing with that interface. If you pass a Person object’s reference to the returnProcessedName method, then it will call the getName implementation that this class or object provides. Similarly, if you pass a Man object’s reference then its implementation will be called. Hence we can say that which implementation of getName will be called will be determined at runtime, which means when the application runs, rather than at compile time, which means when the application is compiled. This runtime association of a request to one of its implementation is known as Dynamic Binding.

Dynamic binding means that issuing a request doesn’t commit you to a particular implementation until run-time. Consequently, you can write programs that expect an object with a particular interface, knowing that any object that has the correct interface will accept the request.

This property is very, very important because Polymorphism depends on it.

So, we have stumbled upon Polymorphism

Dynamic binding lets you substitute objects that have an identical interfaces for each other at run-time. This substitutability is known as polymorphism. It lets a client object make few assumptions about other objects beyond supporting a particular interface. As a result, it simplifies the definition of clients, decouples objects from each other and lets them vary their relationships to each other at run-time. These inter-changeable classes are said to display polymorphic behaviors.

Let us discuss this with respect to the last example.

In our last example, the CertainClass is a client of the Person interface. Since both the Person object and Man object have this interface, we have been able to use both of these objects in the CertainClass. The client class doesn’t even have to know which implementation it is being provided as long as the implementation or object has this Person interface. This is the true meaning of polymorphism, and this client object CertainClass is said to display polymorphic behavior because at run-time it can achieve one of two different behaviors by simply switching between the instances of the Person and Man class like this –

Person newPerson = new Person();
CertainClass c = new CertainClass();

newPerson.setName("Stupid");
String processedName = c.returnProcessedName(newPerson);
System.out.println("Current name: " + processedName);

Man newMan = new Man();
newMan.setName("Stupid");

/**
 * Now you will get name processed in a different
 * way, because implementation is different!
 */
processedName = c.returnProcessedName(newMan);
System.out.println("Current name: " + processedName);

This greatly reduces the complexity of accommodating changes in our application because if you design an application using polymorphism then you can plug in any implementation of this interface in your application without having to test and re-test your application and without breaking any of the existing code.

Does design pattern help us achieve polymorphism ?

Yes, it does! So we have found another use of design pattern –

Design pattern lets us design a flexible application by helping us maintaining true polymorphism in our
application

This is so far I am going to go in this article. I will soon write the second part of this article. Until then, enjoy 🙂 .