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.
| Language | Construct | Typing style | Notable feature |
|---|---|---|---|
| Java | interface | Nominal, declared with implements | Default and static methods since Java 8 |
| C# | interface | Nominal | Default interface methods since C# 8 |
| TypeScript | interface or type alias | Structural | Checked at compile time only |
| Go | interface | Structural, implicit | No implements keyword at all |
| C++ | Abstract class with pure virtual functions | Nominal through inheritance | No dedicated keyword |
| Python | Abstract base class or Protocol | Nominal or structural | Duck typing at run time |
| Rust | trait | Nominal, explicit impl | Static or dynamic dispatch |
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.
| Aspect | Interface | Abstract class |
|---|---|---|
| Purpose | Defines a capability or role | Shares code among related classes |
| Instance state | None | Fields allowed |
| Constructors | None | Allowed |
| Multiple per class | Yes, many interfaces | Usually only one base class |
| Coupling | Low | Higher, tied to the base implementation |
| Typical example | Comparable, Iterable | A base class for UI widgets |
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.
| Situation | Recommended choice | Reason |
|---|---|---|
| Several interchangeable implementations | Interface | Callers stay independent of the variant |
| Need to replace a dependency in tests | Interface | Allows mocks and fakes |
| Related classes sharing much code | Abstract class or composition | Avoids duplicated logic |
| Only one implementation, no variation expected | Concrete class | Avoids needless indirection |
| Public library boundary | Interface with stable methods | Lets the implementation change freely |
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.