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.
The @Override annotation tells the compiler that this method is inherited from the interface.
Let's change the main() method to call the newMethod. Observe that the interface implementation has not changed.
Let's consider an example:
Declare two interfaces with default methods implemented with the same method signature.
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.
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
1. Declaring an interface
Interfaces are declared by specifying a keyword "interface"
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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(); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Implementation of method 1 | |
Implementation of method 2 | |
This is the default implementation of the method |
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.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public interface InterfaceA { | |
default void method(){ | |
System.out.println("Interface A default method"); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public interface InterfaceB { | |
default void method(){ | |
System.out.println("Interface A default method"); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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(); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Default method in implementation class |
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