Interface Segregation: small contracts for real capabilities
Split a broad interface into focused capabilities so each type only promises what it can actually do.
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
- Split interfaces by the clients and capabilities that need them, not simply to make every interface tiny.
- If an implementer throws NotSupportedException for a required member, that can signal that the contract is too broad.
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.