Monday, October 26, 2015

Interfaces in Java8

Interfaces are a key feature of object oriented programming. An interface provides a set of methods that an implementing class must provide. One can assign instances of the class to variables of the interface type. As of Java8, an interface can contain default methods that an implementing class can inherit or override. Default methods (also known as Defender Methods) enable us to add new functionalities to interfaces without breaking the classes that implements the interface.


1. Declaring an interface

Interfaces are declared by specifying a keyword "interface"

public interface MyInterface {
/**
* All the methods of an interface are public by default
*/
void method1();
void method2();
}

2. Implementing an interface

The class implementing the interface has to provide the implementation of all the methods in the interface

public class MyInterfaceImpl implements MyInterface {
@Override public void method1() {
System.out.println("Implementation of method 1");
}
@Override public void method2() {
System.out.println("Implementation of method 2");
}
public static void main(String[] args){
MyInterface obj = new MyInterfaceImpl();
obj.method1();
obj.method2();
}
}

The @Override annotation tells the compiler that this method is inherited from the interface.

Output


Implementation of method 1
Implementation of method 2

3. Default methods in Interface

Java 8 onwards, you can provide default implementation of methods in interfaces. If the class implementing the interface does not provide an implementation of the method, then the default implementation is used.

public interface MyInterface {
/**
* All the methods of an interface are public by default
*/
void method1();
void method2();
default void newMethod(){
System.out.println("This is the default implementation of the method");
}
}

Let's change the main() method to call the newMethod. Observe that the interface implementation has not changed.

public class MyInterfaceImpl implements MyInterface {
@Override public void method1() {
System.out.println("Implementation of method 1");
}
@Override public void method2() {
System.out.println("Implementation of method 2");
}
public static void main(String[] args){
MyInterface obj = new MyInterfaceImpl();
obj.method1();
obj.method2();
obj.newMethod();
}
}

Implementation of method 1
Implementation of method 2
This is the default implementation of the method
view raw Output.txt hosted with ❤ by GitHub

4. Using Default Methods or Abstract Classes

After the introduction of default methods, it may seem that there are no differences between abstract classes, and interfaces. However, it is not so. Abstract classes can define constructor. They can have a state associated with them. In contrast, default methods can only be implemented in terms of invoking other interface methods, with no reference to a particular implementation's state.

5. Default methods and Multiple inheritance ambiguity

A Java class can implement multiple interfaces. Each interface can define default method with same method signature, therefore, the methods can conflict with each other.

Let's consider an example:
Declare two interfaces with default methods implemented with the same method signature.

public interface InterfaceA {
default void method(){
System.out.println("Interface A default method");
}
}
view raw InterfaceA.java hosted with ❤ by GitHub

public interface InterfaceB {
default void method(){
System.out.println("Interface A default method");
}
}
view raw InterfaceB.java hosted with ❤ by GitHub

public class InterfaceImpl implements InterfaceA,InterfaceB{
}

The above code will give a compilation error:
java: class InterfaceImpl inherits unrelated defaults for method() from types InterfaceA and InterfaceB

We need to provide an implementation of the default method in order to resolve this conflict.
public class InterfaceImpl implements InterfaceA,InterfaceB{
@Override public void method() {
System.out.println("Default method in implementation class");
}
public static void main(String[] args){
InterfaceA obj = new InterfaceImpl();
obj.method();
}
}

Default method in implementation class
view raw Output.txt hosted with ❤ by GitHub


Summary

To summarise, default methods enable addition of new functionality without breaking existing implementations.
When we extend an interface containing the default method, we can do one of the following:
1. Not override the default method and the implementing class will inherit the default method.
2. Override the default method similar to other methods we override in subclass.
3. Redeclare default method as abstract, which forces the subclass to override it.

Reference: Java Documentation and D Zone