In Java, an interface is a reference type much like a class, however, it has distinctive features. An interface contains method declarations and serves as literally an interface between a class inheriting that interface and the other classes. Unlike a class, an interface can extend multiple interfaces, and a class can implement multiple interfaces. In this topic, you will discover the importance of interfaces in Java and how they can help.
Why interfaces
One of the OOP principles is abstraction: real-world objects can be represented by their abstract models. When we create these models, we focus on the essential features of the objects. For example, consider a pencil. We can use a pencil to draw. Other properties like its material, or length, might be important at times, but they do not define the idea of what a pencil is.
Imagine you need to design a graphics-editing program. Drawing is the basic function of the program. This tool will prompt the user to select a drawing tool before they can draw anything. They might select a pen, pencil, brush, highlighter, marker, spray, among others. Each tool in the set has specific properties – the marks left by a pencil and a spray are not the same, and that matters. However, all these tools share a common critical feature: the ability to draw.
Next, consider the Pencil class, which is an abstraction of a pencil. As mentioned earlier, at the very least, the class should have a draw method that accepts a model of a curve. This method is fundamental for our program. Let's say Curve is a class that represents some curve:
class Pencil {
...
public void draw(Curve curve) {...}
}Let's define classes for other tools, for example, a brush:
class Brush {
...
public void draw(Curve curve) {...}
}All these tools have the draw method, even though they each use the method differently. The ability to draw is something all these tools share. Let's call this feature DrawingTool. Then we can say that if a class has the DrawingTool feature, then it should be able to draw, which means the class should have the void draw(Curve curve) {...} method.
Java allows declaring this feature by introducing interfaces. This is what our interface looks like:
interface DrawingTool {
void draw(Curve curve);
}It declares the draw method without implementation.
Now let's mark classes that are able to draw by adding implements DrawingTool to the class declaration. If a class implements an interface, it has to implement all declared methods:
class Pencil implements DrawingTool {
...
public void draw(Curve curve) {...}
}
class Brush implements DrawingTool {
...
public void draw(Curve curve) {...}
}Now, with just one glance at the class declaration, it's clear that the class can draw. In essence, interfaces are all about declaring functionality.
Another important advantage of introducing interfaces is that you can use them as a type:
DrawingTool pencil = new Pencil();
DrawingTool brush = new Brush();Now, both a pencil and a brush objects have the same type. It means that both classes can be treated similarly as a DrawingTool. This is another way of supporting polymorphism, which helps to design a reusable drawing function of the graphical editor program.
void drawCurve(DrawingTool tool, Curve curve) {
System.out.println("Drawing a curve " + curve + " using a " + tool);
tool.draw(curve);
}In many situations, it's more important to know what an object can do instead of how it does it. That's why interfaces are widely used for declaring a variable type.
Declaring interfaces
An interface can be considered a special kind of class that can't be instantiated. To declare an interface, you should write the keyword interface instead of class before the name of the interface:
interface Interface { }An interface can contain:
public constants;
abstract methods without an implementation (the keyword
abstractis not required here);default methods with implementation (the keyword
defaultis required);static methods with implementation (the keyword
staticis required);private methods with implementation.
If the modifiers are not specified once the method is declared, its parameters will be public abstract by default.
An interface can't contain constructors, non-public abstract methods, or any fields other than public static final (constants).
Let's declare an interface containing some methods and a constant:
interface Interface {
int INT_CONSTANT = 0; // it's a constant, the same as public static final int INT_CONSTANT = 0
void instanceMethod1();
void instanceMethod2();
static void staticMethod() {
System.out.println("Interface: static method");
}
default void defaultMethod() {
System.out.println("Interface: default method");
}
private void privateMethod() {
System.out.println("Interface: private method");
}
}later we will dive into the differences between these methods but for now, let's just keep in mind that there are different types of them.
Implementing interfaces
A class can implement an interface using the keyword implements. We must provide implementations for all abstract methods of the interface.
Let's implement the interface we considered earlier:
class Class implements Interface {
@Override
public void instanceMethod1() {
System.out.println("Class: instance method1");
}
@Override
public void instanceMethod2() {
System.out.println("Class: instance method2");
}
}Now we can create an instance of the class and call its methods:
Interface instance = new Class();
instance.instanceMethod1(); // it prints "Class: instance method1"
instance.instanceMethod2(); // it prints "Class: instance method2"
instance.defaultMethod(); // it prints "Interface: default method. It can be overridden"Note that we use an Interface as the type of newly created object. In the future, you can make use of polymorphism and change the implementation of this particular Interface to some other.
Here the instance variable has the Interface type, although it is ok to use Class to denote its type.
Class instance = new Class();Conclusion
An interface is a special kind of class that cannot be instantiated. The main idea of an interface is declaring functionality. Interfaces help to abstract from specific classes and emphasize functionality. It makes software design more reusable and clean. It is a good practice to apply the so-called interface-oriented design, which means that you should rely on interfaces instead of concrete implementations. To implement an interface, the keyword implements is used.