Tuesday, August 19, 2008

Abstract Classes and Interfaces

In java, Abstract classes and Interfaces are two building blocks which play an important role nearly in every java program.
Abstract classes are classes which can not be instantiated. It may or may not contain one or more than one methods which have only signature but don't have any body/definition. The methods which don't have body, are called as abstract methods. In order to use abstract classes, one has to extend it and provide definition for all abstract methods. If body of abstract method is not provided in extension class, that child class will also be abstract. Classes are declared abstract with keyword "abstract". Methods are also declared abstract using "abstract" keyword.

public abstract class Shape
{
public abstract void draw();
}

public class Rectangle extends Shape
{
public void draw()
{
//implementation for rectangle
}
}

public class Triangle extends Shape
{
public void draw()
{
//implementation for triangle
}
}

In the above example, Shape is an abstract class which contains one abstact method draw. Each class which extends from Shape like Rectangle and Triangle have to provide its own particular implementation of draw method and that is logical because drawing nature of each Shape is different and each Shape should know how to draw itself. So abstract class Shape provides a bond for all geometry figures that if they are Shape, then they have to provide definition of draw method.

Interfaces are same as Abstract classes in the sense that it contains only those methods which have only signatures but don't have any body. In order to declare interface, "interface" keyword is used before the name of interface. Since interface contains only abstract methods, so "abstract" keyword is not used in method's signature for interface.

public interface Shape
{
public void draw();
}

public class Rectangle implements Shape
{
public void draw()
{
//implementation for Rectangle
}
}

public class Triangle implements Shape
{
public void draw()
{
//implementation for Triangle
}
}

In the above example, an interface "Shape" has been declared which contains one method signature "draw". All those classes which want to have functionality of Shape, implements it and provide body of draw method.

In above examples, i achieved same functionality through abstract class and interface. Now suppose we want to display these shapes on Canvas. For that Canvas class provides a method to add those Shapes and then there is show method of Canvas which internally calls draw method of each Shape added on Canvas as shown below:
public class Canvas
{
private List shapes = new ArrayList();
public void add(Shape shape)
{
shapes.add(shape);
}
public void show()
{
for (Shape s : shapes)
{
s.draw();
}
}
}

public class Main
{
public static void main(String args[])
{
Canvas canvas = new Canvas();
Shape rec1 = new Rectangle();
canvas.add(rec1);
Shape tri1 = new Triangle();
canvas.add(tri1);
canvas.show();
}
}

You can see that Canvas class is usable whether you use Abstract class or interface. Now question arises in which situation one should go for Abstract class and other should go for interface. Suppose above Canvas is used to display both Shapes and Widgets and Canvas does not have any knowledge whether a particular item added on it, is Shape or Widget. Since Widget are not shapes so natural choice in this case is interface approach. There should be an interface like Drawable which should be implemented by both Shapes and Widget. Structure of Shape, Widget, and Canvas is shown below:
public abstract class Shape implements Drawable
{
public void draw();
}

//implementation of Rectangle, and Shape are same as above in abstract class approach, So i //am not mentioning it again.

public abstract class Widget implements Drawable
{
public void draw();
}

//all widgets will extend Widget and implement draw method

public class Canvas
{
private List items = new ArrayList();
public void add(Drawable drawable)
{
items.add(drawable);
}

public void show()
{
for (Drawable item:items)
{
item.draw();
}
}
}

public class Main
{
public static void main(String args[])
{
Canvas canvas = new Canvas();
Shape rec1 = new Rectangle();
canvas.add(rec1);
Widget wid1 = new Widget1();
canvas.add(wid1);
canvas.show();
}
}


So in the light of experience which we have gotten from above examples, i summarize the rule:
  • Use Abstract class for creating a bond between similar items like Rectangle and Triangle are similar entities so extend them from Shape
  • Use interface for creating a bond between dissimilar items like Shape and Widget are different from Canvas.
  • Always try to use Abstract class or interface whenever you need to upcast them to achieve simplicity e.g. add and show method of Canvas.
Now i discuss other properties of interface. Interfaces can also contain fields but those fields will be static and final. Interface can have public or package access. It can also be private only if defined inside of a class as inner interface.

In the last i explain another problem which usually hapens when interfaces are implemented. Supppose there are two interfaces one is ShapeClonable and second one is WidgetClonable. Body of these two interfaces are given below:

public interface ShapeClonnable
{
public Shape clone();
}

public interface WidgetClonnable
{
public Widget clone();
}

Now there is a class Figure which implements both interface as show below:

public class Figure implements ShapeClonnable, WidgetClonnable
{
public Shape clone()
{
//implementation
}

public Widget clone()
{
//implementation
}
}

Figure class contains two methods with same name. It is called method overloading but for that, two methods should have either different number of parameters or differnent types of parameters. In the above case, two methods differ in only return types which are not covered in method overloading, so there will be compile time error. You should give special attention in designing interfaces to avoid this type of error.

No comments: