Java

TOPIC – INTERFACES & POLYMORPHISM

 

 

LESSON NOTE

 

 

WHAT IS AN INTERFACE?

 

An interface is simply a listing of methods without method bodies.  Some interfaces only have one method.  The goal of this/these method(s) is to provide a specific functionality or ability.

 

EXAMPLE OF AN INTERFACE

 

Below is an example interface called Drawable.  Notice that all is has is a listing of three methods: draw, getWidth and getHeight.  Notice that none of the methods have method bodies.

 

public interface Drawable

{

     public void draw();

     public int getWidth();

     public int getHeight();

}

 

WE CANNOT CREATE INTERFACE OBJECTS

 

We can’t instantiate an interface which means we cannot create Drawable objects.  So you will never see Drawable d = new Drawable(); in your code.

 

SO WHAT DOES IT DO?

 

On its own, an interface does nothing.  We use interfaces to define a specific functionality/ability for another class. 

 

For example, the above interface Drawable specifies that the Drawable ability requires that the methods draw(), getWidth(), getHeight() get implemented.  So a class that needs to be Drawable needs to have these methods in it.

 

LET’S CONSIDER THIS CLASS

 

For the purpose of using the Drawable interface, let’s consider this simple Rectangle class:

 

public class Rectangle

{

     public int x,y,w,h;

    

     public Rectangle(int tx, int ty, int tw, int th)

     {

         x=tx;

         y=ty;

         w=tw;

         h=th;

     }

}

 

 

SO HOW DOES A CLASS USE AN INTERFACE?

 

An interface is used by another class to give that class an ability.  We do this by using the implements keyword.

 

For example, we can make the Rectangle class implement the Drawable interface by adding the implements keyword at the end of the class header (see below).

 

public class Rectangle implements Drawable

{

   //…

}

 

REQUIRED IMPLEMENTATIONS

 

If you try typing the above, you will notice that an error is detected.  The reason is that for Rectangle to implement Drawable, it needs to implement the methods that are in Drawable.

 

Below, you see the methods from the interface added to the Rectangle class.

 

public class Rectangle implements Drawable

{

     public int x,y,w,h;

    

     public Rectangle(int tx, int ty, int tw, int th)

     {

         x=tx;

         y=ty;

         w=tw;

         h=th;

     }

 

     public void draw()

     {

         //code to draw Rectangle goes here

     }

 

     public int getWidth()

     {

         //code that returns the drawing width goes here

     }

 

     public int getHeight()

     {

         //code that returns the drawing height goes here

     }

}

 

SO WHY USE INTERFACES?

 

Ok.  So interfaces force us to add methods in classes that implement them.  But we could have added those methods anyway without any interface?  So why bother using an interface?

 

An interface allows us to define an ability.  This ability provides a framework for all classes that need to be Drawable.  All classes that are (or will be) Drawable, need to implement those methods.  It’s a standardization.  This means that all objects that are Drawable can be dealt with in the same way.

 

POPULAR INTERFACES – COMPARABLE & ITERABLE

 

Two of the most known interfaces in Java are Comparable and Iterable.  We can easily implement both of these in our new classes.  And many existing classes also implement these interfaces.

 

In fact, other aspects of Java make use of these interfaces as well.  Java’s Arrays.sort() function, the famous sorting function for arrays, can actually sort any objects that implement Comparable.  More on this in the next lesson.

Java has also developed a special for loop, called the enhanced for loop, that works on any object that implements the Iterable interface.  We will learn more about this later as well.

INTERFACE NAMES

 

An interface name should start with a capital letter.  Some people like Mr. Campeau tend to make sure that their name ends with –able but that is in no way a requirement.


WARNING

 

If you try to look online for example tutorials relating to interfaces, you will find a lot of examples that do not show a useful interface.  While these are factually correct, they tend to be quite confusing.

RECAP

 

An interface is very easy to create.  It’s only a few lines long and provides us with a standard way of defining an ability.

 

POLYMORPHISM – SINGLE LINE

 

We can do the following:

 

     Drawable do = new Rectangle(3, 4, 5, 6);

 

This may seem strange but we can have a Drawable reference to a Rectangle object.  We can only do this because Rectangle is Drawable.  The ability for a reference to refer to a different type of object is called polymorphism (the ability to take on different forms).  Such a reference is called a polymorphic reference.

 

Why might this be useful?

 

A method can receive a Drawable object as parameter and then use it.  This method could be used with different objects that are Drawable.  This is convenient as we do not need to create a new method for each type of object that is Drawable.

 

The ability for a Drawable reference to be made to another object that implements Drawable is called polymorphism.

 

POLYMORPHISM – ARRAY

 

Let’s imagine that you are creating several classes that need to be drawn to screen.  Let’s say their names are Rectangle, Circle, House and Cloud – all things that we might want to draw.  A good approach would be make every class implement the Drawable interface similar to the one in the example above.

 

Once this is done, we can actually create an array of type Drawable.  This array can hold any object that has the Drawable ability, in other words, any object whose class implements Drawable.

 

So we can do something like this:

 

         Drawable[] d = new Drawable[4];

         d[0] = new Rectangle(10, 10, 5, 5);

         d[1] = new Sphere(20, 25, 8);

         d[2] = new Cloud(13, 38, 9);

         d[3] = new House(43, 39, 23, 48);

        

         for (int i=0; i<d.length; i++)

         {

              d[i].draw();

         }

 

The idea that an object can take two different forms (Rectangle can also be a Drawable object) is called polymorphism.

 

Notice how we are conveniently able to process all Drawable objects in the arrays with a simple for loop.  If we want, we can even create other classes that implement Drawable and then add objects of those classes to the same array and they would automatically get drawn.

 

ABOUT POLYMORPHIC REFERENCES

 

Polymorphic references such as Drawable do = new Rectangle(3, 4, 5, 6); can be very convenient as discussed above.  It should be noted that we can only call methods that are in Drawable on the object do.

 

EXAMPLE CODE

 

To understand this example, you need to slowly consider each of the following files.  First, the interface named A with two methods that need to be implemented.  Then, class Bob that implements A overriding both methods and also containing the fin() method.  Then, the Test class creates a polymorphic reference and tries to call a method that is in Bob on a reference of type A – which is an error.  

 

public interface A

{

     public int fun();

     public int fan();

}

 

public class Bob implements A

{

     public int fun()  //override

     {

           return 0;

     }

    

     public int fan()  //override

     {

           return 1;

     }

    

     public int fin()

     {

           return 2;

     }

}

 

public class Tester

{

     public static void main(String[] args)

     {

           A a = new Bob();              //polymorphic reference

           System.out.println(a.fin());   //gives error, fin() is not in A

     }

}