Up to Java 7
, an Interface
could only have abstract methods
and constants only
. implementing class has to implement all the abstract methods of the interface even if that's not required.
package org.wesome.dsalgo.java8;
import java.time.LocalDateTime;
interface Fruit {
void likedFruit(String fruitName);
void showCurrentDate();
}
class Apple implements Fruit {
@Override
public void likedFruit(String fruitName) {
System.out.println("i love = " + fruitName);
}
@Override
public void showCurrentDate() {
System.out.println("today is = " + LocalDateTime.now());
}
}
class Mango implements Fruit {
@Override
public void likedFruit(String fruitName) {
System.out.println("i like = " + fruitName);
}
@Override
public void showCurrentDate() {
System.out.println("today is = " + LocalDateTime.now());
}
}
class MainClass {
public static void main(String[] args) {
System.out.println("========== Apple =========");
Fruit apple = new Apple();
apple.likedFruit("Apple");
apple.showCurrentDate();
System.out.println("========== Mango =========");
Fruit mango = new Mango();
mango.likedFruit("Mango");
mango.showCurrentDate();
}
}
The showCurrentDate
method has common implementation for both the class Apple
and Mango
, but still, they needs to be implemented them or else Fruit
Interface must be declared as Abstract
. If in the future Apple
interface declares a new good to have method, that will break the entire code base, unless all the implementing base classes implements those as well.
To solve these problems Java 8
introduce Default
methods.
Default
methods provide the default implementations in the interface only, the implementing class has the option to override them if required or else Interface implementation will work. The default method is also called as Defender
methods or Virtual
extension methods.
package org.wesome.dsalgo.java8;
interface Tree {
default void liked() {
System.out.println("i like Tree");
}
}
class Fruit implements Tree {
/* no method overridden */
}
class Apple extends Fruit {
/* no method overridden */
}
class Fuji extends Apple {
public static void main(String[] args) {
Tree fuji = new Fuji();
fuji.liked();
}
}
The default
method has a default
prefix and is a non-abstract
method and has a body, like any other method of interface
, the default
methods are public
by default, so no need to specify a public modifier.
The default methods make the interface backwards compatible.
package org.wesome.dsalgo.java8;
import java.time.LocalDateTime;
interface Fruit {
void likedFruit(String fruitName);
default void showCurrentDate() {
System.out.println("today is = " + LocalDateTime.now());
}
}
class Apple implements Fruit {
@Override
public void likedFruit(String fruitName) {
System.out.println("i love = " + fruitName);
}
@Override
public void showCurrentDate() {
System.out.println("today in Apple Country is = " + LocalDateTime.now());
}
}
class Mango implements Fruit {
@Override
public void likedFruit(String fruitName) {
System.out.println("i like = " + fruitName);
}
}
class MainClass {
public static void main(String[] args) {
System.out.println("========== Apple =========");
Fruit apple = new Apple();
apple.likedFruit("Apple");
apple.showCurrentDate();
System.out.println("========== Mango =========");
Fruit mango = new Mango();
mango.likedFruit("Mango");
mango.showCurrentDate();
}
}
In the case of multilevel inheritance, if all the interfaces in the hierarchy have the default method overridden, the last or closest to the derived class will be called.
package org.wesome.dsalgo.java8;
interface Tree {
default void liked() {
System.out.println("i like Tree");
}
}
interface Fruit extends Tree {
default void liked() {
System.out.println("i like Fruit");
}
}
interface Apple extends Fruit {
default void liked() {
System.out.println("i like Apple");
}
}
class Fuji implements Apple {
public static void main(String[] args) {
Tree fuji = new Fuji();
fuji.liked();
}
}