Declaring Functionality With Interfaces in Java

In Java programming language, an interface is a reference type much like a class, however, it has distinctive features. An interface contains method declarations and serves literally as 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, or spray among others. Each tool in the list 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, this abstract 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 in this code:

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 each of them uses the method differently. The ability to draw, is something all these tools share. Let's call this feature — DrawingTool. So we can say that if a class has the DrawingTool feature, it should be able to draw, which means the class should have the void draw(Curve curve) {...} method.

Java allows you to declare 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 which 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 the pencil and the brush objects have the same type. It means that both classes can be treated as a DrawingTool. This is another way of supporting polymorphism, which helps you design a reusable drawing function of the graphics 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 is done. 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 interface keyword instead of class before the name of the interface:

interface Interface { }

An interface can contain:

  • public constants;
  • abstract methods without an implementation (the abstract keyword is not required here);
  • default methods with implementation (the default keyword is required);
  • static methods with implementation (the static keyword is 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 variable:

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 implements keyword. 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 okay 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 and promoting logic in the code. Interfaces help to create an abstraction from specific classes and emphasize functionality. It makes software design clean, more reusable, and ultimately leads to more maintainable code. As an object-oriented programming language, Java encourages the use of interfaces to achieve this level of abstraction. It is a good practice in programming 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 implements keyword is used.

Create a free account to access the full topic

“It has all the necessary theory, lots of practice, and projects of different levels. I haven't skipped any of the 3000+ coding exercises.”
Andrei Maftei
Hyperskill Graduate