Interfaces in Java
In this tutorial, we will study the concept of interfaces in Java. From what they are,how to modify them, how they make smart use of OOP concepts of Inheritance and Polymorphism, we will also implement on how to use them with famous Observer design pattern and finally compare them with Abstract classes. We will also have a look at many examples of when to use each of them to ensure a maximum utilisation of OOPs concepts while designing our world-changing applications.
Interfaces
To start, an interface is just a collection of related methods with no implementation. Let’s straightaway dive into an example for an interface designed for a Car,
interface Car {
// tyre revolutions per minute
void carRpm(int newValue);
void changeGear(int newValue);
void accelerate(int increment);
void applyBrakes(int decrement);
}
When implementing above interface, the name of your class would change (to a particular brand of car, for example, such as FerrariCar), and you'd use the implements keyword in the class declaration:
Class FerrariCar implements Car {
int rpm = 0;
int speed = 0;
int gear = 1;
// The compiler will now need these methods
// carRpm, changeGear, accelerate, and applyBrakes
// all be implemented. Program won’t compile if these
// methods are missing from FerrariCar class.
void carRpm(int newValue) {
rpm = newValue;
}
void changeGear(int newValue) {
gear = newValue;
}
void accelerate(int increment) {
speed += increment;
}
void applyBrakes(int decrement) {
speed -= decrement;
}
void printStates() {
System.out.println("rpm:" +
rpm + " speed:" +
speed + " gear:" + gear);
}
}
Interfaces are like an agreement between the class which implements the interface and the outside world, and this contract is enforced by the compiler at build time. If your class implement an interface, all methods defined by that interface must appear in the class before the class is compiled.
Changing an Interface : Problems and Solutions
Adding new methods to an interface seems pretty simple, just add a new method in the interface and use it in your class. Problem starts when you have implemented that interface in many classes or other people use your interface as well and all their hard-written code is now BROKEN because of you !!!
Let’s look at an example to elaborate above problem and finally build a solution for it:
Consider an interface that you have developed called buyCar:
public interface BuyCar {
void buy(int i);
int buyAnother(int x);
}
Suppose that, in future, you want to add a third method to BuyCar, so that the interface now becomes:
public interface BuyCar {
void buy(int i);
int buyAnother(int x);
boolean isCarNew(int id);
}
If you add this third method, then all classes that implement the old BuyCar interface will break because they no longer implement all methods promised by the BuyCar interface. Programmers relying on this interface will find you and will do <insert really bad things here> to you.
If you want to add additional methods to your old interface, you have several options. You could create a BuyCarNew interface that extends BuyCar:
public interface BuyCarNew extends BuyCar {
boolean isCarNew(int id);
}
Now users of your code can choose to continue to use the old interface or to upgrade to the new interface you defined.
Alternatively, you can define your new methods as default methods. The following example defines a default method named isCarNew:
public interface BuyCar {
void buy(int i);
int buyAnother(int x);
default boolean isCarNew(int id) {
// Method body
}
}
>>> Note : You must provide an implementation for default methods.
Extending Interfaces That Contain Default Methods
When you extend an interface that contains a default method, you must take care of somethings do any of the following:
- Not mention the default method at all, which lets your extended interface inherit the default method with no changes at all.
- Redeclare the default method, which makes it abstract.
- Redefine the default method, which overrides it.
>>> Note : An interface name can be used anywhere a type can be used.
Interfaces and Inheritance
A Java class can implement multiple interfaces. Actually, this is how multiple inheritance can be achieved in Java. Let’s look at an example to understand this:
public interface MagicallyLoyal {
String helpMe();
//interface methods are public by default
}
public interface FastRunner {
void accelerate(int rate);
}
A class which implements both of the above interfaces can be written as:
public class Dog implements MagicallyLoyal, FastRunner {
@Override
public String helpMe() {
return "Help";
}
@Override
public void accelerate(int rate) {
System.out.println("I run very fast! Woof!");
}
}
Notice how the Dog class must implement the inherited abstract methods in the interfaces. Furthermore, notice how a class can practically implement as many interfaces as you want (there is a limit of 65535 due to JVM Limitation).
Interfaces and Polymorphism
Interfaces allow you to use classes in different hierarchies, polymorphically.
For example, say you have the following interface:
public interface Movable {
void moveIt();
}
Any number of classes, across class hierarchies could implement above interface in their own specific way, yet still be used by some caller in a uniform way.
So if you have the following two classes:
public class Car extends Vehicle implements Movable {
public void move() {
//implement move, vroom, vroom!
}}
public class Horse extends Animal implements Movable {
public void move() { //implement move, neigh!
} }
From the perspective of the caller, it's just a Movable
Movable movable = ...;
movable.move(); //who am I?
Observer pattern using Interface
It's very easy to implement the Observer-Listener pattern in the interface, providing more flexibility to the implementing classes.
Consider following example:
interface Observer {
void onAction(String a);
}
interface Observable {
public abstract List<Observer> getObservers();
public default void addObserver(Observer o){
getObservers().add(o);
}
public default void notify(String something ){
for( Observer l : getObservers()) {
l.onAction(something);
}
}
}
Now, any class can be made "Observable" just by implementing the Observable interface, while being free to be part of a different class hierarchy.
abstract class Worker{
public abstract void work();
}
public class MyWorker extends Worker implements Observable {
private List<Observer> allObservers = new ArrayList<Observer>();
@Override public List<Observer> getAllObservers() {
return allObservers;
}
@Override public void work() {
notify("Start the work!");
}
public static void main(String[] args) {
MyWorker worker1 = new MyWorker();
worker1.addListener(new Observer() {
@Override public void onAction(String a) {
System.out.println(a + " (" + new Date() + ")");
}
});
worker1.work();
}
}
Properties of an Interface
- All variables declared in an interface are public static and final
- All methods declared in an interface methods are public and abstract (This statement is valid only till Java 7. From Java 8, you are allowed to have methods in an interface, which need not be abstract; such methods are known as default methods).
- Interface cannot be declared as final
- If more than one interface declares a method that has identical signature, then effectively it is treated as only one method and you cannot distinguish from which interface method is implemented
- A corresponding Interface_Name.class file would be generated for each interface, upon compilation.
When To Use Interfaces
An interface allows somebody to start from beginning to implement your interface or implement your interface in some other code whose original or primary purpose was quite different from the original interface. To them, your interface is only incidental, something that have to add on to their code to be able to use your package. The disadvantage is every method in the interface must be public and you might not want to expose everything.
When To Use Abstract classes
An abstract class, in contrast, provides more structure. It usually defines some default implementations and provides some tools useful for a full implementation. The catch is, code using it must use your class as the base. That may be highly inconvenient if the other programmers wanting to use your package have already developed their own class hierarchy independently. In Java, a class can inherit from only one base class.
When to Use Both
It is possible to offer the best of both ideas, an interface and an abstract class. Users can ignore your abstract class if they wish to. The only drawback of doing it is calling methods via the interface name is slightly slower than calling them via their abstract class name.
Conclusion
In this article, we had a look at the concept of interfaces in Java. From what they are,how to modify them, how they make smart use of OOP concepts of Inheritance and Polymorphism, we also studied on how to use them with famous Observer (or Publisher Subscriber) design pattern and finally compared them with Abstract classes, listing down when to use which. I hope you find this article helpful !
Recent Stories
Top DiscoverSDK Experts
Compare Products
Select up to three two products to compare by clicking on the compare icon () of each product.
{{compareToolModel.Error}}
{{CommentsModel.TotalCount}} Comments
Your Comment