DEV Community

loading...

Interfaces explained

Łukasz Reszke
Open-minded software engineer. Programming mostly in C#. Event Storming facilitator.
・3 min read

Recently I've posted a question on reddit - what is the most difficult for you to understand when you're learning C#? https://www.reddit.com/r/learncsharp/comments/lqpo4i/what_is_the_most_difficult_for_you_to_learn_c/

One of the things that you guys have mentioned was interfaces. Let's put some light on interfaces and their purpose.

What is an interface?

You can think about an interface as a contract that the class implementing that interface has to fulfill. We can say that interface tells us WHAT needs to happen. The class needs to "worry" about HOW to do it. Interface can declare property, event, or method.

public interface ISampleInterface
{
    string Name { get; set; } // Property

    event Action SomethingHappened; // Event

    int Add(int a, int b); // Method
}
Enter fullscreen mode Exit fullscreen mode

Example

Let's take a look at the INotification interface.

interface INotification
{
    void Send(string message);
}
Enter fullscreen mode Exit fullscreen mode

It has only one method declared. The method is Send, which takes message parameter, type of string. Its purpose is to mark the class that implements its interface as a class that can Notify a user about something, by sending a message.

Let's take Email Notifications on the wallpaper.

class EmailNotification : INotification
{
    public void Send(string message)
    {
        // code responsible for sending email
    }
}
Enter fullscreen mode Exit fullscreen mode

The interface is forcing EmailNotification class to implement (write code to execute) Send method. Class implementing an interface has to have exactly the same method declaration.

Does the INotification interface care about the technical details of how the email notification is sent?

Nope, it doesn't. All it has to do is to make sure that this class declares to have the method that is contained in the interface. Technical details are not important. The implementation can be either written by a developer or delegated to an external library.

The important thing is that the class implementing INotification interface declares that it'll send a message to the user, somehow. Class implementing an interface provides an implementation of declared functionalities.

Let's look at example usage. Something happened in the system and it should notify the user about that with some kind of message. Notification preferences normally would be taken from some kind of storage, like a database. For this example, I just used a manually initialized list.

Notice that I am able to initialize a list with the type of Interface that has been declared. Classes implementing this interface can be added to such a list. Thanks to that, in foreach loop, I can execute .Send(string message) method declared by the interface. In effect, user would be notified of every preferred notification method.

    static void Main(string[] args)
    {
        var notificationPreferences = GetUsersNotificationPreferences();

        foreach (var notificationPreference in notificationPreferences)
        {
            notificationPreference.Send(args[0]);
        }
    }

    static List<INotification> GetUsersNotificationPreferences()
    {
        // This should come from user's preferences,
        // which could be stored in database for example
        return new List<INotification>
        {
            new EmailNotification(),
            new SmsNotification(),
            new PushNotification()
        };
    }
Enter fullscreen mode Exit fullscreen mode

Default implementation

Since C# 8.0 an interface may provide a default implementation. It may also define static members in order to provide a single implementation for common functionality.

public interface ILogger
{
    void Log(string message) => Console.WriteLine($"Log: {message}");
}
Enter fullscreen mode Exit fullscreen mode

I am programming mostly in medium-large scale business web applications and we haven't really used it too much. My recommendation is not to abuse it and think twice about whether you really need to have a default implementation.

Class can implement multiple interfaces

One class can implement multiple interfaces.

class EmailNotification : INotification, ILogger
{
    public void Send(string message)
    {
        // code responsible for sending email
    }

    public void Log(string message)
    {
        Console.WriteLine($"Email sent with message: {message}");
    }
}
Enter fullscreen mode Exit fullscreen mode

Interface can implement another interface

interface INotification : ILogger
{
    void Send(string message);
}
Enter fullscreen mode Exit fullscreen mode

Then every class implementing that interface needs to implement the other one as well.

Ok, but how does it help me? Do I really need to split things into WHAT (interface) and HOW (class) to do my project? Well... Interfaces are part of something bigger. But to give you one small example. If you've heard about Dependency Injection you may recall that abstractions should not depend on details. For a simple example, think about architecture with layers. Let's say that there are only two layers, outer and inner. The outer layer declares an interface saying that I need you (the inner layer) to do something. For example, send an email. An engine that is responsible for running the application starts executing a piece of code of the outer layer that declares the need to send an email. Then, it looks for implementation of that interface, so a class that knows how to send an email. How does the "engine" know what class to provide here? It's all set up in something called dependency injection's container, but that's definitely for another topic.

Those are the next steps. I hope I've been able to make interfaces at least a little bit more understandable.

Is there something else that bothers you about interfaces?

Discussion (2)

Collapse
lifelongthinker profile image
Sebastian

Another important thing to mention regarding C# specifically: C# doesn't support multiple inheritance, so implementing multiple interfaces is one way out of this dilemma.

Also, explicit interface implementation is a very powerful concept in C#. It's worth reading into this for advanced devs.

Regarding your examples, I believe two
different, entirely unrelated classes implementing the same interface would have been a good way to illustrate the "implementation vs. interface" dichotomy. INotifyPropertyChanged or IDisposable are good candidates.

Nice article, Łukasz! 👏

Collapse
lukaszreszke profile image
Łukasz Reszke Author

Thanks for the comment, Sebastian 🙏

Another important thing to mention regarding C# specifically: C# doesn't support multiple inheritance, so implementing multiple interfaces is one way out of this dilemma.

Thanks for adding that. It's an important aspect of C#.

Regarding your examples, I believe two
different, entirely unrelated classes implementing the same interface would have been a good way to illustrate the "implementation vs. interface" dichotomy. INotifyPropertyChanged or IDisposable are good candidates.

Great example.