The fourth principle from the solid design principles is called the interface segregation principles
so that's what we're going to take a look at right now.
Now the idea of the interface segregation principle is basically to get you to not create interfaces
which are too large and which require the implementors to maybe implement too much.
So let's suppose you have some sort of a document type so you have struck document and then let's suppose
you want to define an interface for scanning and printing and faxing documents so you could be tempted
to just put all of those operations into a single interface and something called a machine.
So you have some sort of machine which can actually scan documents and fax them or whatever so you add
a bunch of pure virtual methods into it.
You have virtual avoid print which takes a document dork.
And similarly you might have let's say a scan scan as well as facts.
So if you're making a machine which has a multifunction printer which can in fact print and scan and
fax documents there is absolutely no problem in actually using this interface so you can make a structure
called multifunction printer which implements this machine interface.
You simply go into the generation menu implement functions just select everything and you generate the
appropriate members.
And then of course because you have a multifunction device these are all OK you can fill them in with
meaningful stuff.
Now the problem that you typically encounter is what happens if you need to implement just a printer
or just a scanner because you only have this machine interface to work with.
So let's suppose I do want a scanner so I need to implement this machine interface Obviously I go ahead
and I actually generate the stubs for it so I select everything press return and I get my signatures.
Now I am only really OK in terms of implementing this counting functionality I can put something in
here that's meaningful that gives value to the client and everything is OK.
Now the question is Well what do I put inside print.
What do I put inside facts there are different options here.
So for example you might say Well how about we throw some sort of not implemented exception and we basically
throw some exceptions saying you're doing something invalid.
But some people might say well it's OK let's just leave them blank let's leave them as not just empty
bodies.
So if somebody calls scanner the printer they just don't get anything.
Now the problem is that either way what you're doing is you're sending the client a wrong message you're
sending them the message that you've got the scanner which can also print which isn't true but you're
giving them the API anyway simply because the interface that's been defined for handling all of this
stuff is just too big.
And what we really need is we need to segregate the interfaces because no client would require always
to implement both print and scan and fax as well.
So typically what you would do is something like the following.
So instead of this approach you would actually segregate the interfaces so you would have different
interfaces for the princeling the scanning and the faxing as well.
So it would have a structure called maybe a printer which would have virtual voice print.
So this would just take care of printing the document document doc like so it's going to be a virtual
assembly you have yet another interface which might be called eye scanner where you would actually only
require that the scanning is performed and the rest of it is not really important so you would have
a scanner.
And here you would have obviously these scan method and similarly for the fax or I fax machine where
you would where you would fax the documents somewhere.
So having the interface is segregated what this means is that you can now if you want to implement for
example a printer all you have to do is use a struct printer printer and you're good to go because all
you have to do is you have to implement just a single function called print and you don't have to implement
any of the extra functions.
Now if you do want to have some sort of more complicated machine let's suppose you want both printing
and scanning what you can do is you can actually make a new interface so you can make an interface called
a machine which is both an AI printer and an eye scanner like so you don't even have to give them bodies
because you can keep an abstract.
And then if somebody wants to have a concrete implementation of machine they can implement the machine
interface and then they can actually provide the implementations that are required here and furthermore
let's imagine that you have let's say you have a printer already and you have the scanner already so
you have a structure called scanner which implements the scanner interface.
Once again implementing just the scan method.
No other methods are required.
So here you have the scan method and here what you can do with this implementation where you have machine
essentially both in my printer and then my scanner is you can actually build the decorator which is
one of the patterns that we're going to take a look at later on.
So essentially if you once you can make the say you have a reference to a printer and you have an Air
France 2 scanner like so you might want to take them and initialize them in the constructor for example
so you define sort of initialization in the constructor and then when it comes to implementing the members
of a printer in my scanner because you have to implement both.
You can implement them in terms of the things that you've aggregated.
So essentially here I can go into the Albrights so I can actually implement the functions that I need.
So I'm going to implement both of them and here I can implement them in terms of the members so here
for example for printing I can say printed the print the document.
And similarly for scanning I can see scanner thoughts scanned the document.
So very easy and very composable and as a result what we've done I mean the core of the interface segregation
principle is to avoid stuffing too much into a single interface.
And instead if it makes sense if you don't want to force declined to implement too much just break up
your interface into separate interfaces or just at least make them smaller so that whenever a client
uses one of these chunks it's all Kahira.
They don't have to throw exceptions out of methods leave that methods empty nothing like that.
And that's the goal of the interface segregation principle.