Interface in Java
Interfaces in Java are a set of abstract and public methods we want our classes to implement. It is the blueprint of a class and contains static constants and abstract methods.
Interfaces are used to achieve abstraction and implement multiple inheritance.
As complex as it may be to wrap your head around this concept, this article will unravel the world of Interfaces in Java for you with practical examples.
What is an Interface in Java?
An interface is a set of abstract methods you would want your class to implement. These methods are public and abstract by default(you don’t have to explicitly use the “abstract” keyword), and any class implementing your interface will need to provide implementations of those methods.
Intuition behind Using an Interface in Java
Assume you are the head baker of a reputed baking chain, and you want to give instructions to the other bakers under you on the steps they need to follow to bake a cake. You leave them a checklist of things to be done to bake a cake. This is essentially an interface- a checklist! It is a set of methods you want a class to implement to accomplish a certain task.
Now, each baker under the head baker may have his/her way of carrying out each of the different tasks, depending on whether they are baking a Red Velvet Cake or a Truffle Cake. So, they can implement these methods in their own ways.
Here is another example to understand where interfaces are essential –
Assume you are building out a version of the Angry Birds game. Angry Birds is a fun game where the birds can be put on a slingshot to protect their eggs from certain pigs. Your task: you have a few different types of birds, and you need to make them fly.
We could implement it in the following way- using a Bird class as a parent class, and extending specific bird classes from the parent Bird class-
This seems alright so far, but suppose now you decide you want to make a space-themed version of Angry Birds, where you introduce a rocket, and you want to make the rocket fly. Oops! The rocket is not a bird, so you cannot extend the Bird class from the Rocket class. And this is where Interfaces come in. With an interface, you can abstract out the fly method to a new class-like object (the interface) and make all your relevant classes implement this interface.
Neat! This way, you can abstract out the flying property of an object from its definition by using an Interface.
I hope you are now beginning to see the utility of interfaces.
How to Declare and Use an Interface in Java?
In Java, we use the keyword “interface” to declare an interface. The interface can be named using an appropriate identifier. You will often find interfaces being named with an able suffix. For example, we have Runnable, Callable, Comparable, etc. in Java, but this is not a mandatory convention.
Methods may be declared in an interface but should not be implemented. Variables can be declared in an interface, too.
Did you Know?
Methods declared inside an interface are implicitly marked as public and abstract, and variables declared inside an interface are implicitly marked as public static final by the compiler.
Food for thought
Why are member variables in an interface implicitly made public, static, and final?
To use an interface in Java, a class must implement it using the implements keyword and override (provide its own implementations) all the methods declared in the interface.
Although we cannot create objects of an interface, it can be used to reference a class that implements the interface. Use this Java Online Compiler to compile your code
Food for thought
What would happen if a class does not provide implementations of all the methods declared in an interface it is implementing?
Why Use a Java Interface?
- Better polymorphism: With interfaces, you don’t have to make everything fit into one family of classes, offering much more flexibility. Let us look at how we can leverage polymorphism in our cars example
We can take any object that implements the Car interface as a parameter and call the start method on it. How powerful is that!
- Multiple inheritances: In Java, we cannot extend multiple classes because of the famous Diamond problem (explained later in this article). To solve this, we can use a Java interface to give child classes the freedom to extend whatever parent class they wish (and implement our interface) rather than forcing them to extend a specific base class to use our functionality.
- For abstraction: Interfaces help to achieve security, hide certain details, and only show the relevant and necessary information. For example, when we start our car, we just plug in the key and start the car without worrying about the nitty-gritty details of what happens underneath when the car starts. This is a great example of abstraction! We carry out our task, that is, starting the car, but we don’t need to take care of anything else that happens in the background when starting the car.
The Diamond Problem
To understand why multiple inheritances of classes are not allowed in Java, let us look at an example from our Cars scenario. Suppose we want to implement a new class for a Honda Civic Diesel car. Our class will need to extend the DieselCar class. In case we also need to include the properties for a Sedan, then we need our HondaCivic class to extend Sedan as well.
Now, if we have the start method in both the DieselCar as well as the Sedan class, we run into a problem! Which start method should this class inherit? This could cause design issues and is also known as the infamous Diamond Problem. This is also the reason why multiple inheritances are not permitted in Java.
This problem can be solved using an interface, where the Sedan can be an interface that is implemented by the HondaCivic class. Now the HondaCivic class can extend the DieselCar class and implement the Sedan interface, including the appropriate implementation for the start method.
- An interface can be used when we want to achieve 100% abstraction. On the other hand, abstract classes can be used to achieve anything between 0–100% abstraction.
- An interface cannot have constructors because we cannot create objects of an interface.
- If you want a class to achieve multiple inheritances, there is only one way: interfaces.
- If an interface is made private, or if the methods in it are made private or protected, then a compilation error will be thrown.
Implementing Multiple Interfaces in Java
Assume that in our space-themed Angry Birds example, we implement a multi-stage Rocket, and we want the different modules of a rocket to separate at some point.
In this scenario, we can have another interface, Separable, that can be implemented by the Rocket class along with the Flyable interface. This is how a class can implement multiple interfaces, and this is extremely useful when we want to achieve multiple inheritances.
Extending Interfaces in Java
Just like how a class can extend another class, an interface can also extend another. The extends keyword is used here as well, much like in a class. Suppose, in our Angry Birds example, we want our birds to be able to glide along with flying.
Now our Bird classes can implement this interface as well. But since Birds that can glide can fly anyway, instead of having each child class implement two interfaces separately, we can extend the Glidable interface from the Flyable interface as below-
Now, when a Bird class implements the Glidable interface, it must also implement the fly method from the Flyable interface. So now our Canary bird class will look like this-
So we can see that instead of having our Canary class implement both interfaces separately, we can extend the Flyable interface from Glidable and make our Canary class simply implement the Glidable interface.
This concept can also be “extended” to multiple interfaces, where an interface can extend multiple interfaces. The different ways in which an interface can extend other interfaces are given below –
Did you know?
Interfaces cannot extend a class because this would violate the property of an interface that it must contain only abstract methods.
Advantages and Disadvantages of Interfaces in Java
- Interfaces can be used to enforce a contract- that is, provide a specification that classes must implement certain methods if they want to use that interface - Any Car class must implement certain methods like start, stop, etc. This can be enforced by using an interface such that every class implementing the Car interface must implement all the enclosing methods.
- Interfaces are used to achieve multiple inheritance - Our Honda Civic class can extend the DieselCar class and implement the Sedan interface, effectively achieving multiple inheritance from both classes.
- Interfaces can be used to achieve loose coupling - With interfaces, we can ensure that changes in one class do not affect other classes.
- Interfaces expose their member variables since they must be public. This could lead to some issues with respect to predicting the behavior of your code and testing(and the same reasons why one should avoid making class member variables public).
- Since an interface can be thought of as a contract implemented by multiple classes, in certain cases, modifying the interface could lead to unpredictable behavior for the classes implementing them. For example, if a new method is added that is not default, all the old classes will throw compilation errors if those classes do not implement that method. To prevent this, as far as possible, interfaces must be immutable(this could be a disadvantage in certain situations, too).
- If interfaces are not designed carefully, one interface could contain many methods that might not all be needed for a class. Hence, these methods may end up having an empty implementation, which may make your code verbose. To overcome this, interfaces must be designed carefully, keeping the Interface Segregation Principle in mind.
What Has Changed about Interfaces in the Recent Java Versions?
- From Java 8, interfaces can now implement a method and don’t need to be abstract. This is to support backward compatibility, i.e., in older versions of Java, if you add a new method to your interface and you already have classes implementing your interface, you would have to make changes to all of them to implement the new method. Enter default methods in an interface. Since the new method has a default implementation, older classes will not need to implement it. However, newer classes can still override the default method with their own implementations.
- Static methods can also be added to an interface, which can be called directly from outside the interface.
- From Java 9, private methods can also be created within an interface. The only purpose of these methods is to serve as helper methods for other methods since no objects of an interface can be created.
- An interface in Java is a blueprint of a class and contains static constants and abstract methods.
- Interfaces in Java help achieve Polymorphism and Abstraction. They also make it possible to implement Multiple Inheritance in Java.
- When using the Object-Oriented paradigm(OOPs), we should use the Interface Segregation Principle, which talks about how no class should be forced to implement a method it does not use.
- If a class contains a method not implemented by all its child classes, abstract that method into a different interface and make the child classes implement that interface.