Conceptual
First of all, there is a conceptual difference between a class and an interface.
- A class should describe an “is a” relationship. E.g. a Ferrari is a Car
- An interface should describe a contract of a type. E.g. A Car has a steering wheel.
Currently abstract classes are sometimes used for code reuse, even when there is no “is a” relationship. This pollutes the OO design. E.g. FerrariClass
inherits from CarWithSteeringWheel
Benefits
- So from above, you could reuse code without introducing a (conceptually wrong) abstract class.
- You could inherit from multiple interfaces, while an abstract class is only single inheritance
- There is co- and contravariance on interfaces and not on classes in C#
- It’s easier to implement an interface because some methods have default implementations. This could save a lot of work for an implementer of the interface, but the user won’t see the difference 🙂
- But most important for me (as I’m a library maintainer), you could add new methods to an interface without making a breaking change! Before C# 8, if an interface was publicly published, it should be fixed. Because changing the interface could break a lot.
The logger interface
This example shows some of the benefits.
You could describe a (oversimplified) logger interface as follows:
interface ILogger
{
void LogWarning(string message);
void LogError(string message);
void Log(LogLevel level, string message);
}
Then a user of that interface could log easily as warning and error using LogWarning
and LogError
. But the downside is that an implementer must implement all the methods.
An better interface with defaults would be:
interface ILogger
{
void LogWarning(string message) => Log(LogLevel.Warning, message);
void LogError(string message) => Log(LogLevel.Error, message);
void Log(LogLevel level, string message);
}
Now a user could still use all the methods, but the implementer only needs to implement Log
. Also, he could implement LogWarning
and LogError
.
Also, in the future you might like to add the logLevel “Catastrophic”. Before C#8 you could not add the method LogCatastrophic
to ILogger without breaking all current implementations.