Interfaces
in Java always contained method declaration not their definitions
(method body). There was no way of defining method body / definition in
interfaces. This is because historically Java didn’t allow multiple
inheritance of classes. It allowed multiple inheritance of interfaces as
interface were nothing but method declaration. This solves the problem
of ambiguity in multiple inheritance. Since Java 8 it is now possible to
add method bodies in interfaces.
Java 8 has a new feature called Default Methods. It is now possible to add method bodies into interfaces!
public interface Math {
int add(int a, int b);
default int multiply(int a, int b) {
return a * b;
}
}
In above Math interface we added a method multiply with actual method body.Why we need Default Methods?
Why would one want to add
methods into Interfaces? We’ll it is because interfaces are too tightly
coupled with their implementation classes. i.e. it is not possible to
add a method in interface without breaking the implementor class. Once
you add a method in interface, all its implemented classes must declare
method body of this new method.
Since Java 8, things started
getting ugly. A new feature Lambda was introduce which is cool. However
it is not possible to use this feature in existing Java libraries such
as java.util package. If you add a single method in interface
So for backward compatibility, Java 8 cleverly added Default Methods. List, it breaks everything. You need to add its implementation in every class that implements List interface. Imagine in real world how many custom classes would change.Virtual Extension Methods
It added a new concept Virtual extension methods, or as they are often called defender methods,
can now be added to interfaces providing a default implementation of
the declared behavior. So existing interfaces can be augmented without
compromising backward compatibility by adding extension methods to the
interface, whose declaration would contain instructions for finding the
default implementation in the event that implementors do not provide a
method body. A key characteristic of extension methods is that they are
virtual methods just like other interface methods, but provide a default
implementation in the event that the implementing class does not
provide a method body.
Consider following example:interface Person {
//adds a java 8 default method
default void sayHello() {
System.out.println("Hello there!");
}
}
class Sam implements Person {
}
public class Main {
public static void main(String [] args) {
Sam sam = new Sam();
//calling sayHello method calls the method
//defined in interface
sam.sayHello();
}
}
Output:Hello there!
In above code we added a defender method
sayHello() in Person interface. So it was ok for class Sam to avoid declaring this methods body.What about Multiple Inheritance?
Adding method definitions in
interfaces can add ambiguity in multiple inheritance. isn’t it? Well,
it does. However Java 8 handle this issue at Compile type. Consider
below example:
interface Person {
default void sayHello() {
System.out.println("Hello");
}
}
interface Male {
default void sayHello() {
System.out.println("Hi");
}
}
class Sam implements Person, Male {
}
In this example we have same defender method sayHello in both
interfaces Person and Male. Class Sam implements these interfaces. So
which version of sayHello will be inherited? We’ll if you try to compile
this code in Java 8, it will give following error.class Sam inherits unrelated defaults for sayHello() from types Person and Male class Sam implements Person, Male { ^ 1 error
We can solve the above problem by overriding sayHello method in class
Sam.interface Person {
default void sayHello() {
System.out.println("Hello");
}
}
interface Male {
default void sayHello() {
System.out.println("Hi");
}
}
class Sam implements Person, Male {
//override the sayHello to resolve ambiguity
void sayHello() {
}
}
It is also possible to explicitly call method from child class to parent interface. Consider in above example you want to call sayHello method from Male interface when Sam.sayHello is called. You can use super keyword to explicitly call the appropriate method.class Sam implements Person, Male {
//override the sayHello to resolve ambiguity
void sayHello() {
Male.super.sayHello();
}
}
Difference between default methods and abstract class
Ok, so far it looks good. In
Java 8 we can have concrete methods within interfaces.. right.. So how
it is different from Abstract classes? Remember an abstract class is a
class that can not be instantiated (i.e. objects can not be created of)
and which may contain method bodies. Default method in Java 8 looks
similar to Abstract class isn’t it?
We’ll its different
actually. Abstract class can hold state of object. It can have
constructors and member variables. Whereas interfaces with Java 8
default methods cannot hold state. It cannot have constructors and
member variables. You should still use Abstract class whenever you think
your class can have state or you need to do something in constructor.
Default method should be used for backward compatibility. Whenever you
want to add additional functionality in an existing legacy interface you
can use default methods without breaking any existing implementor
classes.
Also abstract classes cannot
be root classes in Lambda expression. What?… I know that’s confusing,
but Lambda expressions are the reason why virtual extension methods were
introduced in Java 8. When a lambda expression is evaluated, the
compiler can infers it into the interface where default method is added.

No comments:
Post a Comment