CodeGym /Courses /C# SELF /Implementing Multiple Interfaces

Implementing Multiple Interfaces

C# SELF
Level 23 , Lesson 2
Available

1. Why implement multiple interfaces?

When you're designing a real system, objects often play more than one "role" — sometimes several at once. Imagine: you have an e-book that you can not only read, but also edit, and even save to the cloud. In object-oriented programming (OOP) terms, this means the object should implement several interfaces at once:

  • IReadable — reading content.
  • IWritable — editing content.
  • ISyncable — syncing with remote storage.

This is exactly where the ability to implement multiple interfaces comes into play. It's a superpower of C# (and OOP in general) that classes don't have: you can't inherit from two or more classes, but you can implement as many interfaces as you want.

Real-life analogy

Imagine an employee at a company. Vasya can be at the same time:

  • A programmer (writes code)
  • A tester (sometimes checks someone else's code)
  • A manager (plans sprints or the daily coffee quota)

These "roles" have totally different responsibilities. But Vasya handles each contract just fine! In programming, it's the same: a class implements interfaces and takes on their "responsibilities."

2. Syntax for implementing multiple interfaces

It's super simple: when declaring a class, just list them separated by commas:


public interface IReadable
{
    void Read();
}

public interface IWritable
{
    void Write(string text);
}

public class Note : IReadable, IWritable
{
    private string content = "";

    public void Read()
    {
        Console.WriteLine("Note: " + content);
    }

    public void Write(string text)
    {
        content = text;
        Console.WriteLine("Note updated!");
    }
}

In this example, the Note class implements both interfaces. That means it must have implementations for both methods: Read and Write.

3. How this looks in "our" app example

In our previous examples, we built a simple banking app for working with accounts. Now let's say we need a universal document class that can be printed (IPrintable), saved to a file (ISavable), and maybe even emailed (IEmailable).

Let's define the interfaces:


public interface IPrintable
{
    void Print();
}

public interface ISavable
{
    void Save(string filePath);
}

public interface IEmailable
{
    void Email(string toAddress);
}

A class that does it all at once:


public class Statement : IPrintable, ISavable, IEmailable
{
    public string Content { get; set; }

    public void Print()
    {
        Console.WriteLine("Printing statement...");
        Console.WriteLine(Content);
    }

    public void Save(string filePath)
    {
        // Using File.WriteAllText from the standard library.
        File.WriteAllText(filePath, Content);
        Console.WriteLine($"Statement saved to file: {filePath}");
    }

    public void Email(string toAddress)
    {
        Console.WriteLine($"Statement sent to email: {toAddress} (simulation)");
    }
}

Now you can use this class in your code however you want:


var stat = new Statement { Content = "Transactions for the month: +1000 units, -500 kd." };
stat.Print();
stat.Save("statement.txt");
stat.Email("boss@bank.corp");

By the way, in practice it's super handy to pass such an object to methods that require specific interfaces, without worrying about its other abilities. For example, a print method can take an IPrintable parameter and have no idea that inside it's also a "saver" and an "emailer."

4. Using interface references: where can you "see" what my object can do?

Here's where the magic starts. When you've implemented multiple interfaces, you can refer to the object as just one of its contracts. For example:


IPrintable printable = new Statement { Content = "Lecture on abstraction" };
printable.Print(); // You can only print

// printable.Save("file.txt"); // Error: IPrintable interface knows nothing about Save.

But if you switch to another interface:


ISavable savable = printable as ISavable;
if (savable != null)
{
    savable.Save("file.txt");
}

This is handy when you pass an object to a method that takes a reference to a specific interface. This approach reduces coupling, and your code becomes super flexible: you can add new implementations without changing old code.

5. Multiple implementation and identical methods in different interfaces

Now it gets interesting! What if two interfaces require a method with the same name, but a different meaning? For example, imagine interfaces for a coffee machine:


public interface IStartable
{
    void Start();
}

public interface IRunnable
{
    void Start();
}

A coffee machine can be both "startable" (IStartable — starts the brewing process) and "runnable" (IRunnable — starts working in general).

Default (regular) implementation:


public class CoffeeMachine : IStartable, IRunnable
{
    public void Start()
    {
        Console.WriteLine("Coffee machine starts for both roles!");
    }
}

In this case, one implementation of Start() "covers" both interfaces.

What if you need different meanings?

You can use explicit interface implementation:


public class CoffeeMachine : IStartable, IRunnable
{
    void IStartable.Start()
    {
        Console.WriteLine("Start: beverage preparation started!");
    }

    void IRunnable.Start()
    {
        Console.WriteLine("Start: machine switched to working mode.");
    }
}

In this case, you can call a specific implementation only through an interface variable:


CoffeeMachine cm = new CoffeeMachine();

IStartable startable = cm;
startable.Start(); // Start: beverage preparation started!

IRunnable runnable = cm;
runnable.Start(); // Start: machine switched to working mode.

// cm.Start(); // Won't compile! Start is not available as a method of the class itself.

By the way, this trick is often used in the .NET standard library — for example, when a class implements several similar interfaces from different frameworks, and each needs its own behavior.

6. Difference between implementing multiple interfaces and inheritance

Feature Class (inheritance) Interfaces
Number of base types Only one As many as you want
Code inheritance Yes (can have base implementation) No, just signatures (except default methods)
State storage Yes No
Adding a new role No (or hard, via composition) Easy, just implement the interface
Best for… "Physical" hierarchies "Roles"/logical capabilities

7. Practical use: "hybrid" objects

Thanks to multiple interface implementation, you can make classes with a unique set of "roles" without worrying about unnecessary inheritance.

For example, in our banking app — you can make a class that can store info about itself, validate itself, and print — all through different interfaces:


public interface IValidatable
{
    bool Validate();
}

public class Check : IPrintable, ISavable, IValidatable
{
    public string Data { get; set; }

    public void Print()
    {
        Console.WriteLine("Printing check: " + Data);
    }

    public void Save(string filePath)
    {
        File.WriteAllText(filePath, Data);
        Console.WriteLine("Check saved: " + filePath);
    }

    public bool Validate()
    {
        return !string.IsNullOrEmpty(Data);
    }
}

This approach lets you build easily extensible architectures, where classes combine roles as needed. If you need to add a new "responsibility" — just implement a new interface.

8. Typical mistakes and gotchas

A common newbie mistake: forgetting to implement all interface members. The compiler won't forgive you here — it'll throw an error and tell you what's missing. It's easy to spot: "Class must implement interface member."

Another common problem — confusion with method accessibility. If you implemented a method explicitly, it's not accessible through the class variable itself — only through the interface.

One more typical situation — refactoring: you make changes to an interface (like adding a method), but don't update all implementations. This leads to compile errors. So when designing, try not to change interfaces after lots of classes already use them.

2
Task
C# SELF, level 23, lesson 2
Locked
Implementing a Simple Class for Multiple Interfaces
Implementing a Simple Class for Multiple Interfaces
2
Task
C# SELF, level 23, lesson 2
Locked
Using interface references
Using interface references
Comments
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION