In object-oriented programming, an interface is a declaration that defines a set of methods that classes can later implement.
If a class implements all the methods of the interface, we say that the class implements or fulfills that interface (if there is even one method the class doesn’t have, it does not implement the interface).
Interfaces define a set of functionalities without specifying how they should be implemented. They only declare the method signatures, leaving their implementation to the classes.
In this way, interfaces provide a very high level of abstraction, as they allow defining what a class can do, without going into how it does it at all.
As they are one of the most important points in object-oriented programming, the ultimate expression of Polymorphism, a better invention than donuts, and at the same time one of the hardest concepts to understand, here comes a daily example! 👇
Purpose of Interfaces
Imagine you have a very important trip tomorrow. You know how to drive, but you don’t have a car. But it’s okay, your boss tells you:
- Tomorrow I’m going to leave a rental vehicle at your door
You go to sleep more relaxed. But suddenly you think “wait a minute… did he say a vehicle? What vehicle? He’s not going to leave me a helicopter, is he? Or a submarine?!”
Of course, because you know how to drive cars. But you have no idea how to drive helicopters, or submarines, or ostriches.

The problem is that your boss told you he would leave an object at your door, but you have no idea if you’ll know how to use it. Well, the same thing happens to your methods with your objects.
One way to solve this is to use an abstract class Car. If your boss tells you he’s going to leave you a rental car, there’s no problem anymore, because you know how to drive.
But another way to do it is if your boss says:
- Tomorrow I’m going to leave you a thing with pedals and a steering wheel that can be driven
Okay, you should really start looking for another job because your boss is very weird. But, you still sleep peacefully. Because he’s going to leave you something that can be driven. And you (again) know how to drive.
In fact, this way is much more versatile. Because now he can not only give you a car. He can leave you a small van, a tractor, or a carnival float… but you will be able to drive it. Because 🌟 —> you know how to drive <— 🌟.
(yes, I’ve been annoying about you know how to drive. We’ll see why in the next section 👇)
Practical Case
Let’s see if we can translate what we explained before into the programming equivalent. What we were saying is that you are a Driver. And drivers have a method that allows them to Drive(...).
class Driver
{
Drive(... something ... );
}
What can you drive? Well, one alternative is to say you can drive Cars. Which would be this.
class Driver
{
Drive(Car car);
}
But I’ve repeated so much that “you know how to drive”. Your method doesn’t know how to drive cars, but anything that can be driven (it’s the same whether it’s a car, a van, or a carnival float).
So now we can be much more general. Translated to the code world, it’s this:
class IDrivable
{
PressPedals(),
TurnSteeringWheel(),
// whatever else is needed
}
class Car implements IDrivable
class Van implements IDrivable
class Float implements IDrivable
class Driver
{
Drive(IDrivable drivable);
}
Now your driver can drive “anything that can be driven”. This includes cars, vans and, even, (I love saying it) carnival floats.
For this, the only condition is that they are IDrivable. Which means they have to have pedals, a steering wheel, and (whatever else is needed, it’s an example).
Interfaces are usually named with an ‘I’ at the beginning.
For example: IDrivable, IFlyable, IPayer…
Interface in Programming
It’s often used to explain interfaces as a “contract” that a class can fulfill. It can be useful to understand the concept but, honestly, I don’t particularly like this explanation.
An interface is called an interface because, literally, it’s an interface. What is the interface of a machine? The elements, or devices, or programs, that you use to interact with it.
In programming, it’s the same,
An interface is the declaration of a way to interact with a class
This comes from a revelation you will have at some point (I hope now) Why does a method need to receive a class? To do things with it. But… what things?
Well, most of the time a method receives an object to do this:
void MyFunction(MyObject obj)
{
obj.MyVariable = 35;
obj.MyMethod("invented_parameter");
}
That is, the vast majority of methods receive an object simply to do . and then whatever (.MyVariable, .MyMethod(...))
And for that, the vast majority of methods don’t need an object of type MyObject. They are just as happy knowing its interface.
interface IMyInterface
{
string MyVariable,
void MyMethod(string),
}
MyObject implements IMyInterface
void MyFunction(IMyInterface obj)
{
obj.MyVariable = 35;
obj.MyMethod("invented_parameter");
}
Because all they need to know is that what they have has the variable .MyVariable, and the method .MyMethod(...) available.
Comparison with Abstract Classes
An interface is similar to an abstract class, in the sense that it defines a set of methods that must be implemented by the classes that use it. In fact, an interface is like an “ultimate super abstract class!!”.
But deep down they have very important differences, both in operation and concept.
In terms of operation, the abstract class can contain implementations of some methods. In fact, this is its main utility, to provide a base. In contrast, an interface is always fully abstract.
In terms of concept, the abstract class implies an inheritance relationship, and an interface implies an implementation relationship. More details in the next point 👇.
When to Use Inheritance and When to Use an Interface
Another of the most frequent doubts you will have is when you should use an interface and when to use inheritance (it doesn’t matter if it’s an abstract class or not).
Sometimes you will get confused because they seem similar, but they are actually two totally different things. Inheritance means belonging, and interface means behavior.
It’s a bit difficult to explain, so I’ll give you a good trick that will help you differentiate one from the other (and in the process understand the concept)
- It’s inheritance if you can say is a
- It’s an interface if you can say can / can be
Let’s see it with two examples:
Inheritance Example
A van is a vehicle
A car is a vehicle
Then there is an inheritance relationship (belonging). van and car are derived classes, and vehicle is a base class.
Interface Example
A van can be driven
A bird can fly
These are implementation relationships (behavior), with IDrivable or IFlyable.
Examples in Different Languages
Let’s see how different languages implement the concept of interface.
In C#, interfaces are declared with the reserved word interface.
public interface IAnimal
{
void MakeSound();
}
public class Dog : IAnimal
{
public void MakeSound()
{
Console.WriteLine("Woof");
}
}
public class Cat : IAnimal
{
public void MakeSound()
{
Console.WriteLine("Meow");
}
}
// Usage
IAnimal dog = new Dog();
IAnimal cat = new Cat();
dog.MakeSound(); // Output: Woof
cat.MakeSound(); // Output: Meow
In C++, interfaces are achieved through abstract classes with at least one pure virtual function.
#include <iostream>
class IAnimal {
public:
virtual void MakeSound() const = 0;
virtual ~IAnimal() = default;
};
class Dog : public IAnimal {
public:
void MakeSound() const override {
std::cout << "Woof" << std::endl;
}
};
class Cat : public IAnimal {
public:
void MakeSound() const override {
std::cout << "Meow" << std::endl;
}
};
// Usage
int main() {
IAnimal* dog = new Dog();
IAnimal* cat = new Cat();
dog->MakeSound(); // Output: Woof
cat->MakeSound(); // Output: Meow
delete dog;
delete cat;
return 0;
}
In JavaScript, there is no native syntax to define interfaces like in other languages. However, we could achieve similar behavior using abstract classes or simply using objects that share a common set of methods.
// We define an object that acts as an "interface" in JavaScript
const IAnimal = {
makeSound: function() {
throw new Error("makeSound method not implemented");
}
};
// Implementation of the Dog class
class Dog {
makeSound() {
console.log("Woof");
}
}
// Implementation of the Cat class
class Cat {
makeSound() {
console.log("Meow");
}
}
// Usage
const dog = new Dog();
const cat = new Cat();
dog.makeSound(); // Output: Woof
cat.makeSound(); // Output: Meow
In TypeScript, interfaces are defined using the reserved word interface.
interface IAnimal {
makeSound(): void;
}
class Dog implements IAnimal {
makeSound(): void {
console.log("Woof");
}
}
class Cat implements IAnimal {
makeSound(): void {
console.log("Meow");
}
}
// Usage
const dog: IAnimal = new Dog();
const cat: IAnimal = new Cat();
dog.makeSound(); // Output: Woof
cat.makeSound(); // Output: Meow
In Python, interfaces are achieved through abstract classes using the abc module.
from abc import ABC, abstractmethod
class IAnimal(ABC):
@abstractmethod
def make_sound(self):
pass
class Dog(IAnimal):
def make_sound(self):
print("Woof")
class Cat(IAnimal):
def make_sound(self):
print("Meow")
# Usage
dog = Dog()
cat = Cat()
dog.make_sound() # Output: Woof
cat.make_sound() # Output: Meow
Best Practices Tips
Interfaces are one of the best tools for maintaining the cleanliness of our program. They allow us to reduce class coupling, which we already know is one of the main problems in OOP.
They also favor code reuse, promote abstraction, reduce inheritance between classes… in short, a marvel. Use them!
Buuut (in life there’s always a but) you have to know how to use them. The main problem you will have is when to use an interface and when to use inheritance. We’ve already seen that in a previous point.
On the other hand, the other difficulty will be how to define an interface. For that, let’s remember that an interface models behaviors, not entities.
For example, you will be very tempted to make an interface for everything. Every class ends up having an interface. You have a User class, and it has its IUser. You have a ShoppingCart class and you make its interface IShoppingCart.
We’ve all done that, and you will too at some point. But in reality, making an interface per class, you are “killing” half the point of interfaces. Interfaces should model behavior. So in the case of User you will have IIdentifiable, IEmailable, or things like that.
But of course, if I don’t separate the interfaces, I end up violating the interface segregation principle, with interfaces with too many methods. But if I separate them too much, I end up almost in duck typing.
So then, where to separate? Well, there’s no magic recipe. It will vary according to your object model, your experience, what your gut tells you… and even then you’ll sometimes mess up (well, it’s okay, you refactor and that’s it).
