The key point of using interfaces is to create loosely coupled types. This is because interfaces are completely abstract and each class that implements them should have its own particular implementation of the interface’s methods.
If you create a base class instead of an interface, all the derived classes are tightly coupled with the base class. In particular situations, this tight coupling can cause some problems. The simplest and the most digestible problem that this tight coupling can cause is to create statically bound behaviors which can limit the code to a particular context. On the other hand loosely coupled types are dynamically bound which means they are more general and more reusable.
For example: imagine that you have one class named Service and another named Customer, if you do:
class Service {
public void RenderService() {…}
…
}
class Customer: Service {
public Customer () {…}
…
}
The Customer class in this example in tightly coupled with the Service class. Imagine if we want to introduce a new Service called Service2. Now, our Customer class will become useless and we need to also introduce another class like Customer2.
Now imagine the use of an interface:
interface IService {
void RenderService();
}
class Service: IService {
public void RenderService() {…}
}
class Customer {
IService service;
public Customer(IService service) {
this.service = service;
}
}
Using this technique (also known as Dependency Injection) you can introduce Service2 by creating another class which also implements the IService interface and still keep your Customer class useful and prevent the need to rewrite it.
Apart from this, there are other reasons to use interfaces such creating highly general (i.e. polymorphic) types or methods. So, as a conclusion, there’s a huge difference between simply writing classes and using inheritance and introducing an interface to your code. I hope I could help you digest the use of interfaces.