Interfaces, Enums and Records
Interface vs abstract class
| Interface | Abstract class | |
|---|---|---|
| Multiple inheritance | A class can implement many | A class extends only one |
| State (fields) | Constants only | Instance fields allowed |
| Constructors | No | Yes |
| Use when | Defining a capability or contract | Sharing code among closely related classes |
interface Shape {
double area();
default String describe() { return getClass().getSimpleName() + " " + area(); }
}
abstract class Base implements Shape {
protected final String id;
Base(String id) { this.id = id; }
}
Enums
An enum is a fixed set of constants; it can have fields and methods.
public enum Level {
BEGINNER(1), INTERMEDIATE(2), ADVANCED(3);
private final int rank;
Level(int rank) { this.rank = rank; }
public int rank() { return rank; }
}
Level l = Level.valueOf("ADVANCED");
switch (l) {
case BEGINNER -> System.out.println("start here");
case ADVANCED -> System.out.println("deep dive");
default -> System.out.println("keep going");
}
Records (Java 16+)
A record is a concise immutable data carrier: the compiler generates the constructor, accessors, equals, hashCode and toString.
public record Point(int x, int y) {
public Point { // compact constructor for validation
if (x < 0 || y < 0) throw new IllegalArgumentException("negative");
}
public double distanceTo(Point other) {
return Math.hypot(x - other.x, y - other.y);
}
}
Point p = new Point(3, 4);
System.out.println(p); // Point[x=3, y=4]
Sealed types (Java 17+)
Restrict which classes may extend a type; combined with pattern matching the compiler can check that all cases are handled.
sealed interface Expr permits Num, Add, Mul {}
record Num(int value) implements Expr {}
record Add(Expr left, Expr right) implements Expr {}
record Mul(Expr left, Expr right) implements Expr {}
static int eval(Expr e) {
return switch (e) {
case Num n -> n.value();
case Add a -> eval(a.left()) + eval(a.right());
case Mul m -> eval(m.left()) * eval(m.right());
};
}
TIP
Prefer composition and interfaces over deep inheritance trees. Use records for plain data and enums instead of "magic" integers or strings.