Skip to content
thesarfo

Concept

Interfaces

What an interface is and why it decouples code, plus the rules around interface methods, multiple implementation, and default methods.

views 0

In Java, an interface is like a contract or blueprint for classes. It defines a set of methods that a class must implement if it wants to claim that it “implements” that interface.

Imagine you’re building a house — a blueprint specifies what each room should look like and what features it should have. The blueprint doesn’t build the house itself, but tells builders how each room should be built. Similarly, an interface specifies what methods a class should have, without providing the implementation — it’s up to the implementing classes to define how those methods work.

Put simply, an interface lets us build loosely coupled components, by putting an interface between our classes and their consumers.

Here’s an example of a tightly coupled program:

TaxCalculator.java
public class TaxCalculator {
private final double taxableIncome;
public TaxCalculator(double taxableIncome) {
this.taxableIncome = taxableIncome;
}
public double calculateTax() {
return taxableIncome * 0.3;
}
}
TaxReport.java
public class TaxReport {
private TaxCalculator calculator;
public TaxReport() {
calculator = new TaxCalculator(500_000);
}
public void show() {
var tax = calculator.calculateTax();
System.out.println(tax);
}
}

TaxReport is tightly dependent on TaxCalculator — if we add an extra parameter to the TaxCalculator constructor, TaxReport breaks and needs to be reconfigured too.

Creating an interface

Interfaces are strictly used to achieve polymorphism. If you don’t have any shared implementation to give to the subclass, use an interface rather than an abstract class. An abstract class can have abstract methods, and a child class inheriting from it is forced to override them to be usable — in that scenario, an interface works just as well. An interface can be viewed as an abstract class where every method is abstract.

In Java, a class can only extend one class, but a class implementing an interface can implement multiple interfaces.

By creating an object of an interface type and calling overridden methods on it, we achieve dynamic method dispatch — runtime polymorphism.

// example of how to create an interface
interface IMusicPlayer {
void play();
void stop();
}
class Phone {
public void call() {
System.out.println("Phone call");
}
public void sms() {
System.out.println("Phone sending SMS");
}
}
interface ICamera {
void click();
void record();
}
interface IMusicPlayer {
void play();
void stop();
}
class Smartphone extends Phone implements ICamera, IMusicPlayer {
public void videoCall() {
System.out.println("Smart phone video calling");
}
@Override
public void click() {
System.out.println("Smart phone clicking photo");
}
@Override
public void record() {
System.out.println("Smart phone recording video");
}
@Override
public void play() {
System.out.println("Smart phone playing music");
}
@Override
public void stop() {
System.out.println("Smart phone stopped playing music");
}
}
public class InterfaceExample {
public static void main(String[] args) {
Smartphone sp = new Smartphone();
sp.play();
sp.click();
sp.call();
sp.record();
ICamera c = new Smartphone();
c.click();
c.record();
IMusicPlayer m = new Smartphone();
m.play();
m.stop();
Phone p = new Smartphone();
p.sms();
p.call();
}
}

Looking at the example above, it’s the same Smartphone object, but we can use it as a phone, camera, or music player — achieving polymorphism.

Do’s and don’ts of interfaces

Rules

  1. Inside an interface, by default all methods are public and abstract — whether you write public/abstract explicitly doesn’t matter.
  2. You cannot make interface methods private, because they’re meant to be implemented by classes.
  3. You can have an identifier (variable) in an interface, but its name should be in CAPS, so it’s recognizable as an interface constant.
  4. These identifiers are static and final (constant) by default, so whether you add those keywords explicitly doesn’t matter.
  5. A method in an interface can’t have a body because it’s abstract — unless you mark it static, in which case it can have a body.
  6. An interface can extend another interface.
  7. An interface can have a default method — unlike abstract methods, a default method has a body. Any implementing class can choose to override it or not; if not overridden, the interface’s own implementation applies.
  8. You can also have a private method in an interface. A private method can only be used by a default method inside the same interface — it can’t be used outside the interface.

Why we use default methods

Normally, every class implementing an interface must implement all of its methods, or the class itself becomes abstract. This means that when we add a new method to an existing interface, every implementing class would break (since it would now have to override the new method too) — we couldn’t change the interface without affecting every child class. A default method solves this: we can add one to an interface, and every implementing class can choose to override it or not — either way, it still has access to the method, and doesn’t become abstract just because a new method was added.