A real world analogy
For the sake of keeping the answer simple, let's say that the only cars that exist are personal vehicles with an automatic gearbox, and let's exclude stick shift and larger vehicles such as buses or trucks.
If you have a driver's license, then you are able to drive any car. Even if you learned to drive in a BMW, you'll also be able to drive a Mercedes or a Fiat. Why is that?
Well, simply put, because all these cars have exactly the same layout. Every car implements this same layout, which is why you can change cars and still know exactly how to operate that new car:
- The steering wheel can be turned lef/right to turn the car left/right
- The right pedal makes the vehicle go forward
- The left pedal makes the vehicle stop going forward
- The gear stick allows you to (dis)connect the engine from the wheels
What I have listed here is a complete list of all interactions between a driver and a car that are required for a driver to correctly drive that car.
This "list of possible interactions" is what we call an interface. When you look at both definitions you supplied, you'll see that they fit with my example:
Methods form the object's interface with the outside world
Translated: "Pedals/steering weel/gear stick form the car's interface with the driver".
a point where two systems, subjects, organizations, etc. meet and interact.
The pedals/steering weel/gear stick are the only points where a driver and car interact with one another.
Interfaces in programming
I can think of a Java interface as an entity that sits between two objects
We need to be very careful with our words here. Some real life examples exist where an interface is an object between two actors, e.g. how a translator facilitates communication between two people who speak different languages.
However, in programming terms, the predominant example is where one actor owns another actor, rather than them being two "cooperating" individuals. In this case, the interface is actually referring to (part of) the owned actor itself, rather than a separate layer that sits inbetween them.
Pedantically, your class doesn't need to implement an interface
to "have an interface". Class methods are an "interface" by themselves, as they describe how a consumer can interact with this class.
However, this scenario invariably ties the class and the "interface" together, i.e. this so-called "interface" only applies to this specific class, and each class has its own "interface".
That's not very useful, since it completely excludes the possibility of multiple classes implementing the same interface, similar to how many cars have the exact same layout for the driver.
So instead of letting the class define its own interface, we create a separate interface
, which is often called a "contract", i.e. a list of requirements that a class needs to fulfill if it wants to correctly claim that it implements the interface.
When we have that separate interface, we can then have our classes (however many we want) implement that interface.
A simple example:
public interface ICar
{
void Steer(Direction direction);
void Accelerate();
void Brake();
}
public class BMW318 : ICar
{
public void Steer(Direction direction)
{
// make the car turn in the requested direction
}
public void Accelerate()
{
// make the car accelerate
}
public void Brake()
{
// make the car brake
}
}
public class Fiat500 : ICar
{
public void Steer(Direction direction)
{
// make the car turn in the requested direction
}
public void Accelerate()
{
// make the car accelerate
}
public void Brake()
{
// make the car brake
}
}
To a layman, most cars nowadays seems to be exactly the same, mechanically speaking.If that's how you feel, then the above example doesn't really showcase the power of interfaces.
So I want to take the time here and show you how an interface allows an object to fulfill the same contract but have a completely different implementation:
public class Horse : ICar
{
public void Steer(Direction direction)
{
// pull the reins left/right
}
public void Accelerate()
{
// kick the spurs on the horse
}
public void Brake()
{
// pull the reins and yell "Woah boy!"
}
}
public class Donkey : ICar
{
public void Steer(Direction direction)
{
// pull carrot and stick left/right
}
public void Accelerate()
{
// hold a carrot in front of the donkey
}
public void Brake()
{
// let the donkey eat the carrot
}
}
This Horse
and Donkey
are dramatically different from a BMW318
, yet they still can be operated using the same instructions.
Now that we have these examples, let's showcase the power of an interface in action. The below code works exactly the same for every implementation of ICar
:
public void DriveToTheShop(ICar car)
{
// car is at the house
car.Accelerate();
car.Brake();
car.Steer(Direction.Left);
car.Accelerate();
car.Brake();
// car arrives at the shop
}
This is the power of an interface. We're able to define interactions with an object without even knowing what that object is (is it a car? is it a horse? is it a donkey?). The only requirement we have is that all possible objects (BMW318
, Fiat500
, Horse
, Donkey
) correctly fulfill the interface
that we defined.
Your interpretation of an interface
When you look at this setup, you could say that there are five "things" in the codebase (ICar
, BMW318
, Fiat500
, Horse
, Donkey
). I think you think of an interface
as a separate layer because it is a separate "thing" in the codebase.
I think that what you're intending to say is correct, but the way you are saying it is ambiguous and leaves your words open for an interpretation where it is not correct.
While it is true that the interface
is a separate "thing" in the codebase (which we often refer to as an "abstraction layer"), it's often better to think of the interface as being part of a given implementing class (e.g. Fiat500
), because the class owns its implementation of that interface.
When we're dealing with an object, e.g. a Fiat500
, then the best way to think of it is that the Fiat500
is an ICar
, not that there's a separate ICar
interface.