Why interfaces?
Do you drive a car? If not, I assume you know what driving a car generally entails (steering wheel, accelerator, brake). The rest of the answer assumes you drive a car and have a car that is a different brand than mine.
Have you ever driven my car? No. But if given access, would you be able to drive my car without needing to learn how to drive my car? Yes.
The same applies to me. I've never driven your car, but I would be able to drive it without needing to learn how to drive it.
Why is that? Because all cars share the same interface. Steering wheel, accelerator on the right, brake in the middle. No two cars are exactly the same, but they are built in a way that the interaction between a driver and any car is exactly the same.
Compare this to an F16 fighter jet. Being able to drive a car does not make you able to pilot a jet because its interface is different. It doesn't have a steering wheel, it doesn't have accelerator/brake pedals.
The main benefit is clear: drivers don't need to learn how to drive every car individually.
Now, to complete the analogy, the general concept of a car is an interface, whereas specific cars are classes. The main benefit is clear: you don't need to write custom code for every similar class.
A practical example
public class BMW
{
public SteeringWheel SteeringWheel { get; set; }
public Pedal Accelerator { get; set; }
public Pedal Brake { get; set; }
}
public class BMWDriver
{
public void ParticipateInRace(BMW myBMW)
{
myBMW.Accelerator.Press();
myBMW.SteeringWheel.TurnLeft();
myBMW.SteeringWheel.TurnRight();
myBMW.Accelerator.Release();
myBMW.Brake.Press();
myBMW.Brake.Release();
}
}
This driver only knows how to drive a BMW.
public class Audi
{
public SteeringWheel SteeringWheel { get; set; }
public Pedal Accelerator { get; set; }
public Pedal Brake { get; set; }
}
public class AudiDriver
{
public void ParticipateInRace(Audi myAudi)
{
myAudi.Accelerator.Press();
myAudi.SteeringWheel.TurnLeft();
myAudi.SteeringWheel.TurnRight();
myAudi.Accelerator.Release();
myAudi.Brake.Press();
myAudi.Brake.Release();
}
}
This driver only knows how to drive an Audi.
But in reality, a driver would be able to drive any car (that has a steering wheel and two pedals).
So how do we tell the compiler that any car can be used? We give them a commonality they both share: the interface.
public interface ICar
{
SteeringWheel SteeringWheel { get; }
Pedal Accelerator { get; }
Pedal Brake { get; }
}
public class BMW : ICar { /* same as before */ }
public class Audi : ICar { /* same as before */ }
public class Driver
{
public void ParticipateInRace(ICar anyCar)
{
anyCar.Accelerator.Press();
anyCar.SteeringWheel.TurnLeft();
anyCar.SteeringWheel.TurnRight();
anyCar.Accelerator.Release();
anyCar.Brake.Press();
anyCar.Brake.Release();
}
}
We now have a more generalized Driver
who is able to drive any car that has a steering wheel and two pedals.
Why not inheritance?
half of the time I am like well if you create a class and inherit it would it not do the same thing? what am I missing here?
In some cases, inheritance would work. However, inheritance is generally an inferior solution, especially when you get into more complex codebases or more advanced architectures.
Don't worry, all developers once loved inheritance and then needed to learn to not use inheritance as a cure-all. It's part of the normal lifecyle of a developer :)
One of the biggest reasons why is that you can't derive from more than one class, but you can implement multiple interfaces.
Let's say we have three types of sports that can be done
public class Runner
{
public void Run() { /* running logic */ }
}
public class Swimmer
{
public void Swim() { /* swimming logic */ }
}
public class Cyclist
{
public void Cycle() { /* cycling logic */ }
}
Now we need to create a specialized sport which entails running, e.g. basketball.
public class BasketBallPlayer : Runner
{
public void ThrowBall() { /* throwing logic */ }
// Running is already inherited from Runner
}
Great, no problems yet. But now, we need to create a triathlete class, which entails all three sports (running, swimming, cycling)
public class Triathlete: Runner, Swimmer, Cyclist { ... }
And this is where the compiler breaks down. It refuses to allow you to inherit from multiple base classes at the same time. The reasons are much deeper than this answer can delve into, Google it if you want to know more.
However, had we used interfaces:
public interface IRunner
{
void Run();
}
public interface ISwimmer
{
void Swim();
}
public interface ICyclist
{
void Cycle();
}
Then the compiler would've allowed this:
public class Triathlete: IRunner, ISwimmer, ICyclist
{
public void Run() { /* running logic */ }
public void Swim() { /* swimming logic */ }
public void Cycle() { /* cycling logic */ }
}
And this is why interfaces generally beat inheritance (among other reasons).
There are more reasons why interfaces are generally better, but this is the biggest one. Google it if you want more explanation, I can't delve into it all for a StackOverflow answer.