Lesson 107 min read

Interfaces & Abstract Classes

Make a promise your code must keep

What Is an Interface?

An interface is a contract. It says "if you sign this contract, you promise to have these methods and properties." It doesn't tell you how to do them — just that you must do them.

Think of it like a job description. A "driver" must be able to StartEngine(), Steer(), and Stop(). Whether they're driving a car, bus, or spaceship doesn't matter — they all fulfill the same contract.

Why is this useful? Because you can write code that works with any object that implements the interface, without caring about its specific type. Your code just says "give me something that can drive" and it works with cars, buses, and spaceships.

Defining & Implementing Interfaces

// Interface — the contract
interface IPlayable
{
string Title { get; } // must have a Title
double Duration { get; } // must have a Duration (in minutes)
void Play(); // must be able to Play
}
// Song implements IPlayable
class Song : IPlayable
{
public string Title { get; }
public string Artist { get; }
public double Duration { get; }
public Song(string title, string artist, double duration)
{
Title = title;
Artist = artist;
Duration = duration;
}
public void Play()
=> Console.WriteLine($"♪ Playing '{Title}' by {Artist} ({Duration} min)");
}
// Podcast also implements IPlayable
class Podcast : IPlayable
{
public string Title { get; }
public string Host { get; }
public double Duration { get; }
public Podcast(string title, string host, double duration)
{
Title = title;
Host = host;
Duration = duration;
}
public void Play()
=> Console.WriteLine($"🎙 Playing '{Title}' hosted by {Host} ({Duration} min)");
}
// Works with ANY IPlayable!
void PlayAll(IPlayable[] playlist)
{
double total = 0;
foreach (var item in playlist)
{
item.Play();
total += item.Duration;
}
Console.WriteLine($"Total time: {total} minutes");
}
IPlayable[] myPlaylist = {
new Song("Bohemian Rhapsody", "Queen", 5.9),
new Podcast("Code Talk", "Dev Dan", 45.0),
new Song("Imagine", "John Lennon", 3.1)
};
PlayAll(myPlaylist);
Output
♪ Playing 'Bohemian Rhapsody' by Queen (5.9 min)
🎙 Playing 'Code Talk' hosted by Dev Dan (45 min)
♪ Playing 'Imagine' by John Lennon (3.1 min)
Total time: 54 minutes

Multiple Interfaces — Wear Many Hats

A class can only inherit from one parent class (single inheritance), but it can implement as many interfaces as it wants. Built-in interfaces like IComparable are what power sorted data structures such as binary search trees. It's like a person who is both a "swimmer" AND a "runner" AND a "cook" — they fulfill all those contracts simultaneously.

Since C# 8, interfaces can also have default implementations — meaning you can provide a method body right in the interface. Classes that implement the interface get that method for free but can still override it if they want.

Multiple Interfaces & Default Methods

interface IPrintable
{
void Print();
}
interface ISaveable
{
void Save(string path);
// Default implementation (C# 8+)
void AutoSave()
{
Save("./auto-backup.txt");
Console.WriteLine("Auto-saved!");
}
}
interface IShareable
{
void Share(string recipient);
}
// Document implements ALL THREE interfaces
class Document : IPrintable, ISaveable, IShareable
{
public string Content { get; set; }
public Document(string content) => Content = content;
public void Print()
=> Console.WriteLine($"Printing: {Content}");
public void Save(string path)
=> Console.WriteLine($"Saved to {path}");
public void Share(string recipient)
=> Console.WriteLine($"Shared with {recipient}");
}
var doc = new Document("My Report");
doc.Print();
doc.Save("/documents/report.txt");
doc.Share("[email protected]");
// Access the default method through the interface
ISaveable saveable = doc;
saveable.AutoSave();
Output
Printing: My Report
Saved to /documents/report.txt
Shared with [email protected]
Saved to ./auto-backup.txt
Auto-saved!

Abstract Class vs Interface — When to Use Which?

They seem similar, so here's the cheat sheet:

  • Interface: Pure contract. No state (until C# 8 defaults). A class can implement many. Use when unrelated classes need the same capability (like IPrintable).
  • Abstract class: Partial blueprint. Can have fields, constructors, and both implemented AND abstract methods. A class can inherit only one. Use when classes share a common identity (like all Shapes).

Rule of thumb: If it's a "can do" relationship (can print, can save), use an interface. If it's an "is a" relationship (is a shape, is an animal), use an abstract class.

Note: 🤝 Interface naming convention: In C#, interface names start with a capital I — like IPlayable, IDisposable, IComparable. This makes them instantly recognizable in your code. It's not a rule the compiler enforces, but every C# developer expects it.

Quick check

How many interfaces can a class implement?
Inheritance & PolymorphismCollections & Generics