14
Lesson 14 of 35 · OOP

Interfaces & Polymorphism

Interfaces define a contract—a set of members that implementing classes must provide. Combined with polymorphism, interfaces are the foundation of loosely-coupled, testable designs.

Defining and Implementing an Interface

Declare an interface with the interface keyword. By convention names start with I. A class implements an interface using the : syntax (same as inheritance).

Interface IShape.cs
public interface IShape
{
    double Area();
    double Perimeter();
    string Describe() => $"Area={Area():F2}"; // default impl
}

public class Triangle(double a, double b, double c) : IShape
{
    private double s => (a + b + c) / 2;
    public double Area()      => Math.Sqrt(s*(s-a)*(s-b)*(s-c));
    public double Perimeter() => a + b + c;
}

IShape t = new Triangle(3, 4, 5);
Console.WriteLine(t.Describe()); // Area=6.00

Polymorphism

Polymorphism means 'many forms'. When a variable of an interface type holds objects of different implementing types, the correct method is called based on the actual runtime type.

Polymorphism demo Poly.cs
IShape[] shapes = { new Circle(5), new Rectangle(4, 6), new Triangle(3,4,5) };

foreach (IShape s in shapes)
    Console.WriteLine($"{s.GetType().Name}: {s.Describe()}");

Dependency Injection Pattern

Interfaces enable Dependency Injection (DI)—one of the most important design patterns. Rather than a class creating its dependencies, they are passed in through the constructor, making code easy to test and swap.

DI pattern DI.cs
public interface ILogger { void Log(string msg); }

public class ConsoleLogger : ILogger
{
    public void Log(string msg) => Console.WriteLine($"[LOG] {msg}");
}

public class OrderService(ILogger logger)
{
    public void PlaceOrder(string item)
    {
        logger.Log($"Order placed: {item}");
    }
}

ILogger logger = new ConsoleLogger();
var svc = new OrderService(logger);
svc.PlaceOrder("Widget"); // [LOG] Order placed: Widget