Java 8 interfaces and abstract classes


Java opened up many new rules in the 1.8 implementation. One of them is the restriction of having a declared method inside the Java interfaces. Now in Java 1.8 you can also declare a method with a body by using the keyword “default”. You can also have methods declared as “static”, that have a body too in the interface. Both default and static methods in the interface are implicitly public. If the APIs needed to add a few functionalities, then the Java architects could have created abstract class extending those interfaces and could have added the methods on them rather than changing the rules to allow for the methods with body in the interfaces. These allowances also blur some distinction between the interface and abstract class. There is a difference between these two keywords. The default keyword can be overridden by the implementing classes if they so please. They are referred by the instance variables of the implementing class only. They cannot be referenced directly through the interface. Let’s define an interface called Vehicle, which has two default methods start( ) and stop( ), and a static method race( ). The method drive( ) is the interface’s abstract method.


public interface Vehicle {
             
       public default void start(){
              System.out.println("Vehicle started !!!");
       }
      
       public default void stop() {
              System.out.println("Vehicle stopped !!!");
       }
      
       public void drive();
      
       public static void race(){
              System.out.println("Ready to Race ? !!!");
       }
}


Let’s look at the usage before we describe the methods further. We override the default method start( ), and implement the abstract method drive( ). We leave the other default method stop( ), unchanged by not overriding it.


public class Car implements Vehicle {

       @Override
       public void drive() {
              System.out.println("Driving Car !!!!!");            
       }
      
       @Override
       public void start(){
              System.out.println("Car Started !!!");
       }

       public static void race() {
              System.out.println("Racing Car !!!!");
       }
      
      
       // print car values
       public static void main(String... args) {
              Car c = new Car();
              c.start();
              c.drive();
              c.stop();
             
              // static methods
              Vehicle.race();    
             Car.race(); 
       }
}

Looking at code above, you can notice these:
·         The default and the abstract methods are accessed by the instance variable of the object (Car) implementing the interface. They cannot be accessed like the class level methods.
·         The static methods can be referenced by the interface name and are similar to static method in classes (Vehicle.race( ) and Car.race( )), and can only be accessed as a class level reference. There is no such thing as “overriding” for static methods, (this was always there in Java) as it is evident with the method race ( ).

Few reasons why the Java architects decided on allowing methods with body are:
1.       The interfaces in use are difficult to modify. It is impossible to add new functions without asking the implementing classes to implement those abstract functions. It is a lot of code change for programmers who have already coded and upgrading the java version might break their code. All new releases must be backward compatible. The default allows for a backdoor entry and upgrading of exiting interfaces without breaking the existing code. Besides, most of these interfaces have been around for decades and needed a revamp or addition.
2.       The new java additions for lambda expressions, functional interfaces and java streams, would have required a complete new set of classes and a huge list of abstract classes to implement them. This would have added a lot of duplicate APIs which essentially do the same thing.
3.       The static methods in the interfaces allow for adding utilities to the interface and its inheritors. Does this mean that you should be using interface with static methods to create a collection of utility methods? Absolutely not! The interfaces can be implemented by many classes, and you might not like your utilities to be inherited in this way. It is always prudent to write your utility methods in class with a private constructor to prevent initialization. More details on writing a utility class is in another section dedicated to it.

Since Java allows for multiple interface implementations you might implement two (or more) interfaces having similar default method declaration. How will your class decide which default method to execute when being called? Well to prevent this the Java compiler enforces the rule that you must explicitly override the method in your code, to resolve the conflict.

Since Java 1.8 allows default and static methods it poses a dilemma for the new programmers on what should they use when defining a library of classes – interfaces with static and default methods or abstract classes. The earlier rules have not actually changed. Remember abstract classes are used to define an abstraction of a root class (nouns). Interfaces on the other hand are common traits (verbs or functions) that are independent of the object hierarchy. In fact, since interfaces are now allowed default and static methods, it takes away the need to define certain features in utility classes or forcefully define an abstract class just to keep a set of common methods.

Comments

Popular posts from this blog

Java Generics - 7. Upper and Lower Bounds

Java Functional Programming : 3. The java.util.function Library

Java Generics - 3. Multiple bounding