Sunday, March 22, 2015

Abstract class vs Interfaces in Java

After introduction of default methods in Java 8, even interfaces can have methods with implementation. The major motivation for introduction of default methods is to add new methods (with body) to the existing interfaces without breaking the existing implementation of those interfaces. Read this post.

An abstract class is a class that is marked abstract and it may or may not have abstract methods. This cannot be instantiated but it can be subclassed. Consider an example of a class BinarySearchTree which has methods addNode/removeNode etc. We know AVLTree and RedBlackTree are also binary search trees but they support rotation. We can create an abstract class RotatableBinarySearchTree which extends BinarySearchTree and also introduce two methods rotateLeft and rotateRight. Now the trees AVLTree and RedBlackTree can extend this abstract class RotatableBinarySearchTree.

Abstract class vs Interface
There are following similarities or differences between the two:

Abstract classInterface
Cannot be instantiated.Same for interfaces.
Can contain mix of declared and implemented methods.Same for interfaces.
We can declare fields that are not static and final.All fields are by default public, static and final.
We can declare concrete methods which are public, protected or private.All methods (declared or defined) are by default public.
We can only extend one (abstract or not)A class can implement any number of interfaces.

Now the question is when to use abstract class and when to use interface. If you are in doubt always prefer interface but here are the guidelines that can help.

Prefer abstract class if:

  • We want to share code among many closely related classes. An example if of AVLTree and RedBlackTree I mentioned before.
  • If we have a set of classes that share common methods or fields or they require access modifier other than public, in that case abstract class can be a good fit.
  • If we want to declare non-static or non-final fields. This enables us to define methods that can access and modify the object's state to which they belong.

Prefer interface if: In my opinion use interface in all other scenarios. For example:

  • If we expect unrelated classes to implement our interface e.g. Serializable is implemented by many unrelated classes.
  • If we want to specify only the behavior of a particular data type and not concerned about its behavior e.g. Tree interface which has methods add, remove, height, size etc. which can be implemented by various tree classes.
  • If we want to use multiple inheritance.

We know that if a class implements an interface it must implement all its methods but in case of an abstract class if subclass implements all the abstract methods of super class it is fine else the subclass itself must be declared abstract. Suppose we got a situation where a class wants to implement an interface but does not want to implement all its methods. For example:
public interface Demo{  
    void methodA();
    void methodB();
    void methodC();
    void methodD();
}

public class DemoClass implements Demo{
 public void methodA(){
         System.out.println("in methodA");
        }
 public void methodB(){
         System.out.println("in methodB");
        }
}

This will lead to compilation problem as all the methods of interface Demo are not implemented. In such a situation we can create an abstract class which implements the interface and provides implementation body for other two methods.
public interface Demo{  
 void methodA();
 void methodB();
 void methodC();
 void methodD();
}
abstract class AbstractDemo implements Demo {
 public void methodC(){
      System.out.println("in methodC");
 }
 public void methodD(){
      System.out.println("in methodD");
 }
}
public class DemoClass exends AbstractDemo{
 public void methodA(){
         System.out.println("in methodA");
    }
 public void methodB(){
         System.out.println("in methodB");
    }
}

An abstract class can have static fields and methods and we can use them with a class reference as AbstractClass.staticMethod() as we do with any regular class. That's all folks. Hope you liked it :).

5 comments:

Deepak A L said...

Can you post more examples of java 8 ?

Houssem said...

//interfaces could be instantiated IMO

/* interface */
interface Car {
void run();
}


/*instantiate Car interface */

Car car = new Car() {
@Override
public void run() {
System.out.println("run");
}
};

car.run();
}

//our input is
run

Deepak A L said...

The above java code is not working "!
Can you post complete interface working example

Akhil Mittal said...

@Houssem: You cannot instantiate an interface. What you are doing is actually instantiating an anonymous class that implements the concerned interface.

Anonymous said...

Nice one. This is one of the frequently asked Java Interview Question. I have seen it many times but yet I like it most because it give you an opportunity to show your understanding of object oriented concepts like Inheritance, Abstraction and Polymorphism.