Interface

On this page 6

An interface in object-oriented programming is a named contract that lists the operations a type must provide, usually as method signatures without implementation. A class that implements the interface promises to supply those methods, and other code can then work with any object that fulfills the contract without knowing its concrete class.

Interfaces are the main tool for separating what an object does from how it does it. They work closely with the neighboring concepts of the class, the object, inheritance, polymorphism and encapsulation: an interface defines a type, classes implement it, and polymorphism lets one variable of the interface type refer to objects of many different classes.

How an interface defines a contract

An interface declares a set of method signatures: names, parameter types and return types. It normally contains no instance fields and no state. A class declares that it implements the interface and must then provide a body for every method, otherwise the compiler rejects it or the class stays abstract.

The value of the contract lies in programming against the interface. A method that accepts a PaymentGateway parameter works with every class that implements it, whether that class talks to a card processor, a bank transfer service or a test double. The caller depends only on the contract, which is the core idea of the dependency inversion principle.

An interface also forms a type in its own right. Variables, parameters, return values and collections can use it, and the actual object behind the reference is chosen at run time. This is subtype polymorphism without the coupling of shared implementation.

Interfaces can also be generic, which lets one contract work with many element types while keeping full type safety. The generic forms of Comparable in Java and IEnumerable in C# are standard examples: the same contract describes ordering or iteration for strings, dates or custom types, and the compiler checks every use.

A special case is the marker interface, which declares no methods at all and only tags a class as having a property, as Serializable does in Java. Modern code often replaces marker interfaces with annotations or attributes, because a tag that carries no behavior adds little to the type contract.

Interfaces across programming languages

Languages implement the interface concept in different ways, and the differences affect how code is designed. The main distinction is between nominal interfaces, which a class must declare explicitly, and structural interfaces, which a type satisfies simply by having the right methods.

LanguageConstructTyping styleNotable feature
JavainterfaceNominal, declared with implementsDefault and static methods since Java 8
C#interfaceNominalDefault interface methods since C# 8
TypeScriptinterface or type aliasStructuralChecked at compile time only
GointerfaceStructural, implicitNo implements keyword at all
C++Abstract class with pure virtual functionsNominal through inheritanceNo dedicated keyword
PythonAbstract base class or ProtocolNominal or structuralDuck typing at run time
RusttraitNominal, explicit implStatic or dynamic dispatch
How major languages express interfaces

Structural typing reduces boilerplate and allows an interface to be defined after the types that satisfy it, which is common in Go. Nominal typing makes intent explicit and prevents accidental matches, where two unrelated methods merely share a name and signature.

In dynamically typed languages the contract is often informal. Python code relies on duck typing, where an object qualifies if it has the expected methods at run time, and Protocol classes let static type checkers verify the same contract before the program runs.

Interface compared with abstract class and inheritance

An interface and an abstract class both describe types that cannot be used on their own, but they serve different purposes. An abstract class shares implementation and state among closely related classes, while an interface only defines capability and can be implemented by unrelated classes.

AspectInterfaceAbstract class
PurposeDefines a capability or roleShares code among related classes
Instance stateNoneFields allowed
ConstructorsNoneAllowed
Multiple per classYes, many interfacesUsually only one base class
CouplingLowHigher, tied to the base implementation
Typical exampleComparable, IterableA base class for UI widgets
Interface versus abstract class

Because most languages forbid multiple inheritance of implementation but allow a class to implement several interfaces, interfaces are the standard way to give one class several roles. A class can be Serializable, Comparable and Closeable at once without inheriting conflicting code. This supports the guideline to favor composition over inheritance.

Designing good interfaces

A well-designed interface is small, cohesive and named after a role. The interface segregation principle states that clients should not be forced to depend on methods they do not use, so several narrow interfaces are usually better than one broad one.

The following decision table shows when an interface is the right choice and when another construct fits better.

SituationRecommended choiceReason
Several interchangeable implementationsInterfaceCallers stay independent of the variant
Need to replace a dependency in testsInterfaceAllows mocks and fakes
Related classes sharing much codeAbstract class or compositionAvoids duplicated logic
Only one implementation, no variation expectedConcrete classAvoids needless indirection
Public library boundaryInterface with stable methodsLets the implementation change freely
When to introduce an interface

Interfaces also have costs. Adding a method to a published interface breaks every existing implementation, which is why Java and C# introduced default methods. A common mistake is to create an interface for every class by reflex, producing one-implementation interfaces that add files and indirection without real flexibility. Another is a so-called fat interface that mixes unrelated responsibilities and forces implementers to write empty methods.

In everyday language

An interface is a promise about what something can do, without saying how it does it. Think of a standard wall socket. Any lamp, phone charger or kettle with the right plug works with it. The socket does not care which brand made the device.

In software, an interface is that standard plug shape. A program says it needs something that can, for example, send a message. Any piece of code that keeps the promise can be plugged in, and it can be swapped later without rebuilding the rest.

Seen in the real world

An online shop sends order confirmations and must support email today and text messages later. The developers define an interface called NotificationSender with a single method send(recipient, message).

The order processing code receives a NotificationSender and calls send without knowing how delivery happens. An EmailSender class implements the interface for launch. In automated tests, a small fake implementation records messages instead of sending them, so tests run in milliseconds without a mail server.

When the shop adds text message notifications a year later, the team writes an SmsSender class that implements the same interface and changes one line of configuration. The order processing code stays untouched, and its existing tests continue to pass.