Lesson 17 โข Advanced
Interfaces & Abstraction Best Practices
Default methods, sealed interfaces, and interface-first design principles.
๐ Before You Start
You should be comfortable with:
- Interfaces & Abstract Classes (Lesson 11) โ basic contracts
- Inheritance (Lesson 10) โ extends, polymorphism
- Design Patterns (Lesson 16) โ Factory, Decorator patterns
What You'll Learn
- โ Default methods in interfaces (Java 8+)
- โ Static methods in interfaces
- โ Private methods in interfaces (Java 9+)
- โ Sealed interfaces (Java 17+)
- โ Interface vs abstract class decision guide
- โ Interface-first (contract-first) design
1๏ธโฃ Interface Evolution in Java
๐ก Analogy: USB Standards โ An interface is like a USB standard. Any device that follows the spec can plug in. Default methods are like backwards-compatible upgrades โ USB-C added features while old devices still work. Sealed interfaces restrict which connector types are allowed.
The Diamond Problem: When a class implements two interfaces with the same default method, Java forces you to override it explicitly โ ensuring no ambiguity.
2๏ธโฃ Sealed Interfaces (Java 17+)
Sealed interfaces restrict which classes can implement them using the permits clause. This enables exhaustive pattern matching in switch expressions.
public sealed interface Shape permits Circle, Rectangle, Triangle {
double area();
}
// Compiler guarantees all cases handled
double describe(Shape s) {
return switch (s) {
case Circle c -> Math.PI * c.radius() * c.radius();
case Rectangle r -> r.width() * r.height();
case Triangle t -> 0.5 * t.base() * t.height();
}; // No default needed!
}Try It: Default Methods & Multiple Interfaces
See how default methods enable backward-compatible API evolution
// ๐ก Try modifying this code and see what happens!
// Default Methods & Multiple Interfaces (Simulated)
console.log("=== Default Methods ===\n");
// Interface with default method
class Printable {
toString() { throw new Error("Must implement toString()"); }
printFormatted() {
console.log(" [Formatted] " + this.toString());
}
}
class Product extends Printable {
constructor(name, price) { super(); this.name = name; this.price = price; }
toString() { return this.name
...3๏ธโฃ Contract-First Design
The principle: "Program to an interface, not an implementation." Define what your code does before deciding how it does it. This makes swapping implementations trivial.
// โ Good: Code depends on interface List<String> names = new ArrayList<>(); // can swap to LinkedList // โ Bad: Code depends on implementation ArrayList<String> names = new ArrayList<>(); // locked in
Try It: Contract-First Payment System
Build a payment system where implementations can be swapped freely
// ๐ก Try modifying this code and see what happens!
// Contract-First Design (Simulated)
console.log("=== Contract-First Design ===\n");
// Define the contract (interface)
// PaymentProcessor must have: processPayment, refund, getBalance
class StripeProcessor {
constructor() { this.balance = 1000; this.name = "Stripe"; }
processPayment(amount) {
this.balance -= amount;
return { id: "stripe_" + Date.now(), amount, provider: this.name };
}
refund(txnId) { console.
...4๏ธโฃ Abstract Class vs Interface Comparison
| Feature | Interface | Abstract Class |
|---|---|---|
| Multiple inherit | โ Yes | โ No |
| Constructor | โ No | โ Yes |
| State (fields) | constants only | โ Yes |
| Default methods | โ Yes (Java 8+) | โ Yes |
| Access modifiers | public only | any modifier |
Decision rule: "Can do" โ Interface. "Is a" โ Abstract class. When in doubt โ Interface.
Try It: Sealed Interface Pattern Matching
Simulate sealed interfaces with exhaustive pattern matching
// ๐ก Try modifying this code and see what happens!
// Sealed Interfaces (Simulated)
console.log("=== Sealed Interface Simulation ===\n");
// Simulating sealed interface Shape permits Circle, Rectangle, Triangle
class Circle {
constructor(radius) { this.radius = radius; this.type = "Circle"; }
area() { return Math.PI * this.radius * this.radius; }
}
class Rectangle {
constructor(w, h) { this.w = w; this.h = h; this.type = "Rectangle"; }
area() { return this.w * this.h; }
}
cla
...5๏ธโฃ Common Mistakes
6๏ธโฃ Pro Tips
๐ก Program to an interface, not an implementation โ use List<String>, not ArrayList<String>.
๐ก Sealed interfaces + records = algebraic data types in Java for functional-style pattern matching.
๐ก Decision rule: "Can do" โ Interface. "Is a" โ Abstract class.
๐ Quick Reference
| Feature | Syntax | Since |
|---|---|---|
| Default method | default void m() {} | Java 8 |
| Static method | static void m() {} | Java 8 |
| Private method | private void m() {} | Java 9 |
| Sealed interface | sealed interface permits A, B | Java 17 |
| Functional interface | @FunctionalInterface | Java 8 |
๐ Lesson Complete!
You now understand modern interface design including default methods, sealed types, and contract-first architecture!
Next: Inner Classes & Anonymous Classes โ static, non-static, local, and anonymous inner classes.
Sign up for free to track which lessons you've completed and get learning reminders.