π Chapter 8: Java Interfaces β The Ultimate Contract
1. What is an Interface? (The Power Outlet Analogy)
Think of an Interface as a "Contract" or a "Standard."
Imagine you are looking at a power outlet on your wall. The outlet doesn't care if you plug in a lamp, a toaster, or a laptop. As long as the device has the standard plug (the interface), it will receive power. The outlet defines the shape and the output, and the device provides the implementation (using that power to make light or heat toast).
In Java, an interface is a collection of abstract methods (methods without a body). When a class "implements" an interface, it is signing a legal contract: "I promise that I will provide a working version of every method listed in this interface."
2. Defining and Implementing an Interface
To create an interface, we use the interface keyword instead of class. To use it, a class uses the implements keyword.
Java
// The Interface (The Contract)
interface WaterVehicle {
void floatOnWater(); // No body, just the requirement
void dock();
}
// The Implementation (The Promise Keeper)
class Boat implements WaterVehicle {
@Override
public void floatOnWater() {
System.out.println("The boat is buoyant and floating.");
}
@Override
public void dock() {
System.out.println("The boat is secured to the pier.");
}
}
Important Rules:
- Implicitly Abstract: Methods in an interface are automatically public and abstract. You don't even have to type those keywords.
- No State: You cannot have instance variables (like int speed;) in an interface. You can only have constants (public static final).
- No Objects: You cannot say new WaterVehicle(). Just like abstract classes, interfaces are incomplete.
3. The Superpower: Multiple Interfaces
This is where interfaces beat inheritance. A class can implement as many interfaces as it wants.
Java
interface Flyable { void fly(); }
interface GPS { void getCoordinates(); }
class Drone implements Flyable, GPS {
public void fly() {
System.out.println("Propellers spinning... taking off!");
}
public void getCoordinates() {
System.out.println("Latitude: 40.7, Longitude: -74.0");
}
}
By using interfaces, the Drone class now has multiple "types." It is a Drone, it is a Flyable thing, and it is a GPS device. This is the ultimate form of Polymorphism.
4. Interfaces vs. Abstract Classes: Which One to Choose?
This is a classic interview question and a common point of confusion. The choice usually boils down to the "Is-a" vs. "Can-do" relationship.
Feature | Abstract Class | InterfaceRelationship | "Is-a" (A Dog is an Animal) | "Can-do" (A Phone can take photos)
Inheritance | Single (Only 1 parent) | Multiple (Unlimited interfaces)
State | Can have variables (fields) | Cannot have variables (only constants)
Purpose | To share code among closely related objects. | To define a common behavior for unrelated objects.
Inheritance | Single (Only 1 parent) | Multiple (Unlimited interfaces)
State | Can have variables (fields) | Cannot have variables (only constants)
Purpose | To share code among closely related objects. | To define a common behavior for unrelated objects.
Example: A Bird and an Airplane are totally different things, but they both "Can-do" the act of flying. Therefore, Flyable should be an interface, not an abstract parent class.
5. Modern Java: Default and Static Methods
Before Java 8, interfaces were strictly "empty" contracts. If you added a new method to an interface, you would "break" every single class that implemented it (because they would suddenly be missing a method).
To solve this, Java introduced Default Methods. These allow you to add a method with a body to an interface without breaking existing code.
Java
interface Camera {
void takePhoto();
// A default method with a body
default void startTimer() {
System.out.println("Timer started... 3, 2, 1...");
}
}
Any class implementing Camera will automatically get the startTimer functionality, but they can still override it if they want a custom timer.
6. Functional Interfaces and a Hint of Lambdas
If an interface has exactly one abstract method, it is called a Functional Interface. These are special because they are the foundation for "Functional Programming" in Java (Lambdas).
Java
@FunctionalInterface
interface Alarm {
void trigger();
}
In modern Java, instead of writing a whole class just to implement trigger(), you can use a shortcut called a Lambda Expression:
Alarm myAlarm = () -> System.out.println("WAKE UP!");
(We will dive deep into Lambdas in a later chapter, but it's good to see how interfaces make this possible!)
7. Practical Example: The Smart Home System
Let's see how a professional might use interfaces to build a "Smart Home" controller that manages different devices.
Java
interface Connectable {
void turnOn();
void turnOff();
}
class SmartLight implements Connectable {
public void turnOn() { System.out.println("Light: Brightness 100%"); }
public void turnOff() { System.out.println("Light: Off"); }
}
class SmartThermostat implements Connectable {
public void turnOn() { System.out.println("AC: Powering on to 72 degrees"); }
public void turnOff() { System.out.println("AC: Hibernating"); }
}
public class HomeApp {
public static void main(String[] args) {
// We can treat different objects as the SAME type (Connectable)
Connectable[] devices = { new SmartLight(), new SmartThermostat() };
for (Connectable device : devices) {
device.turnOn(); // Polymorphism!
}
}
}
By using the Connectable interface, our HomeApp doesn't need to know if it's talking to a light or a thermostat. It just knows that both devices have a turnOn() button. If we buy a SmartToaster tomorrow, we just make it implement Connectable, and it will work with our app instantly.
π Chapter Summary
In this chapter, we learned about the "Social Contract" of Java:
- Interfaces define what a class must do, but not how it does it.
- They allow for Multiple Inheritance of Behavior, letting a class play many roles.
- Default Methods allow interfaces to evolve without breaking old code.
- They promote Loose Couplingβmaking your code more modular and easier to update.
You have now mastered the pillars of Object-Oriented Programming: Encapsulation, Inheritance, Polymorphism, and Abstraction.