Interface Segregation: small contracts for real capabilities

Split a broad interface into focused capabilities so each type only promises what it can actually do.

Time O(1) callSpace O(1)Code C++, Python and C#
Watch it animatedStep through it, with the running line highlighted. Free with an account.

The idea

StartShift needs only IWork. HumanWorker can also implement IEat, while RobotWorker is not forced to invent an Eat method it cannot meaningfully perform.

Code

class Workable {
public:
    virtual void work() = 0;
    virtual ~Workable() = default;
};
class Eatable {
public:
    virtual void eat() = 0;
    virtual ~Eatable() = default;
};
class HumanWorker : public Workable, public Eatable {
public:
    void work() override {}
    void eat() override {}
};
class RobotWorker : public Workable {
public:
    void work() override {}
};

void startShift(Workable& worker) {
    worker.work();
}

int main() {
    RobotWorker robot;
    startShift(robot);
}
from typing import Protocol

class Works(Protocol):
    def work(self) -> None: ...

class Eats(Protocol):
    def eat(self) -> None: ...

class HumanWorker:
    def work(self) -> None: pass
    def eat(self) -> None: pass

class RobotWorker:
    def work(self) -> None: pass

def start_shift(worker: Works) -> None:
    worker.work()

start_shift(RobotWorker())
interface IWork {
    void Work();
}
interface IEat {
    void Eat();
}
class HumanWorker : IWork, IEat {
    public void Work() { }
    public void Eat() { }
}
class RobotWorker : IWork {
    public void Work() { }
}

static void StartShift(IWork worker) {
    worker.Work();
}
StartShift(new RobotWorker());

Tips

In the .NET library

Interface Segregation pairs naturally with capability interfaces such as IReadable, IWritable, or IAsyncDisposable. Keep names and contracts tied to useful behavior.