Skip to main content

Interfaces

A contract with no implementation attached: a list of method signatures a class promises to honor, and nothing about how it honors them. A class describes what an object is. An interface describes what an object can do.

«interface»PaymentMethod+ pay(amount)+ refund(amount)CreditCard...PayPal...Crypto...
Three unrelated classes, one shared promise. None of them knows the others exist.

A checkout flow that holds a PaymentMethod reference never learns whether it is charging a card, debiting a wallet or moving a coin. Ship Apple Pay next year and the checkout code does not change - one more class keeps the same promise, and nothing that already worked notices the addition. This is the entire reason interfaces exist: programming to an interface, not an implementation is one of the four pillars (abstraction, specifically), and it is what Design principles means when it talks about depending on an abstraction rather than a concrete class - this page is where that idea gets its concrete tool.

Implementing multiple interfaces

A class can implement as many interfaces as it likes, because promising to do several unrelated things costs nothing until you actually write the methods:

class Duck implements Swimmable, Flyable, Comparable<Duck> {
public void swim() { /* ... */ }
public void fly() { /* ... */ }
public int compareTo(Duck other) { /* ... */ }
}

Compare that to inheritance: a class extends exactly one other class in most languages, because it is inheriting real, concrete code, and resolving a conflict between two implementations of the same method from two parents ("diamond inheritance") is genuinely ambiguous. A conflict between two interfaces' method signatures is not ambiguous in the same way - there is no implementation to collide, only a name to promise.

Interface vs abstract class

Both let you program to an abstraction, and both show up constantly in machine-coding interviews, which is exactly why the distinction gets asked about directly.

InterfaceAbstract class
ImplementationNone - pure signatures (plus default/static methods in languages that allow them)Can mix finished methods with abstract ones
State (fields)No instance fieldsCan hold instance fields
How manyA class can implement any numberA class can extend exactly one
ConstructorNoneCan have one, run via super()
Use it whenUnrelated classes share only a signatureSubclasses share real, reusable implementation

Reach for an interface when unrelated classes need to promise the same behavior and nothing else - a Bird and an Airplane share zero code but can both promise fly(). Reach for an abstract class when subclasses genuinely share implementation and only differ in specific, well-defined places - that shared code is the entire reason to inherit.

An abstract class earns its keep the moment two subclasses would otherwise duplicate the same finished method. SalariedEmployee and HourlyEmployee both need to clockIn() and clockOut() in an identical way; only calculatePay() actually differs between them.

«abstract»Employee+ name+ id+ clockIn()+ clockOut()+ calculatePay()SalariedEmployee+ calculatePay()HourlyEmployee+ calculatePay()
The starred method is abstract - a promise. The other two are finished code every subclass gets for free.

That mix - some methods finished, one left as a promise - is exactly what a plain interface cannot offer on its own, since a plain interface cannot finish any method at all.

Default and static interface methods

Several languages (Java 8+, C# 8+, Kotlin) let an interface supply a method body directly, so implementers only need to override it if the default is wrong for them:

interface PaymentMethod {
void pay(double amount);
 
default void refund(double amount) {
throw new UnsupportedOperationException("refunds not supported");
}
}

CreditCard and PayPal can override refund; a hypothetical GiftCard that never supports refunds can simply not bother, and it still compiles because the interface supplied a body. This blurs the line with an abstract class slightly, but the core difference holds: a default method still cannot hold instance state, and a class can still implement any number of interfaces that each bring default methods, which is not true of abstract classes.

Static interface methods are the interface's equivalent of a static class method - a utility function that belongs to the type, not to any implementer, like Comparator.comparing(...) in Java's standard library.

Marker interfaces

An interface does not need to declare any methods at all. A marker interface - like Java's Serializable or Cloneable - carries zero methods on purpose; implementing it is itself the signal. Other code checks obj instanceof Serializable to decide whether an object is allowed to be written to a stream, without calling any method the interface defines, because it defines none. Modern code often reaches for an annotation instead (@Serializable) for the same purpose, but the marker-interface shape still turns up in older APIs and in languages without a first-class annotation system.

Try it yourself: Shape needs Circle, Square and Triangle to all expose area(), sharing zero implementation. Separately, Employee needs SalariedEmployee and HourlyEmployee to share clockIn()/clockOut() but calculate pay differently. Which one gets an interface and which gets an abstract class, and why? Then: would a Taggable marker interface with no methods make sense for flagging which of your classes support a generic "add a label" feature, or would a plain boolean field on each class do the same job with less machinery?

Check yourself

Question 1 of 4

A checkout flow holds a PaymentMethod reference and calls pay(amount) without knowing if it is a CreditCard, PayPal or Crypto object. What made that possible?