3.5.4 How to Achieve Encapsulation Using Interfaces

We have been using a form of encapsulation for a while now that we haven't pointed out. Whenever we declare a parameter or a return type we are saying that we only want a certain type of something and we can only send a certain thing back. Doing this prevents garbage from getting in or out of our methods. In the example below the only thing that can be passed in is a string and the only thing able to be returned is a Food type.

The same idea can be applied to interface types.

Let's say the Animal in the Zoo has a method called EatFood that does some stuff and has a parameter of type Food.

The custodian is tasked with feed the Cheetah today and has two Food objects with him, some CheetahChips and some CheetahKibble. Since they both inherit from the Food class, either one of the objects can get passed in as an argument and the custodian gets confused and accidentally gives the Cheetah human food instead of animal food. Not good.

But wait, the CheetahKibble implement IAnimalFood! We can change the parameter type from Food to IAnimalFood.

Now we don't have to worry about the custodian getting confused they can't send the human food as an argument if they wanted to.

And the CheetahKibble that implements IAnimalFood works just fine.

We can also break encapsulation a little bit by using interfaces as a return type. Let's take a look at a method the custodian has.

The method can return only one type of thing: a Restroom. But what if we want to return a booth? The custodian could clean that, right? Womp womp.

But wait, they're both ICleanables! If we change the return type to ICleanable the Booth object can be returned as well. We don't care about what specific thing it is we just care that it's cleanable.