The answer is quite simple.
How to handle objects that can do more than you expect?
You do not need to handle it because it would serve no purpose. An interface is usually designed depending on how it's going to be used. If your interface does not define washing hands, then you do not care about it as the interface caller; if you did you would have designed it differently.
For example, in case it is morning time and if it is just an animal then you call eat, otherwise if it is a human, then call first washHands, getDressed and only then call eat. How to handle this cases?
For example, in pseudocode:
interface IEater { void Eat(); }
interface IMorningRoutinePerformer { void DoMorningRoutine(); }
interface IAnimal : IEater, IMorningPerformer;
interface IHuman : IEater, IMorningPerformer;
{
void WashHands();
void GetDressed();
}
void MorningTime()
{
IList<IMorningRoutinePerformer> items = Service.GetMorningPerformers();
foreach(item in items) { item.DoMorningRoutine(); }
}
Now you implement IMorningPerformer
for Animal
to just perform eating, and for Human
you also implement it to wash hands and get dressed. Caller of your MorningTime method could care less if it's human or an animal. All it wants is the morning routine performed, which each object does admirably thanks to OO.
Polymorphism dies.
Or does it?
You need to find out the type of the object
Why are assuming that? I think this could be a wrong assumption.
Is there a common approach to handle this cases?
Yes, usually it's solved with carefully designed class or interface hierarchy. Note that in the example above there is nothing that contradicts your example as you've given it, yet, you probably will feel dissatisfied, because you've made some more assumptions that you did not write in the question as of the moment of writing, and these assumptions are probably violated.
It is possible to go to a rabbit hole by you tightening your assumptions and me modifying the answer to still satisfy them, but I do not think that would be useful.
Designing good class hierarchies is difficult and it requires a lot of insight into your business domain. For complex domains one goes over two, three or even more iterations, as they refine their understanding of how different entities in their business domain interact, until they arrive at an adequate model.
That's where simplistic animal examples are lacking. We want to teach simple, but the problem we are trying to solve is not obvious until you go deeper, that is have more complex considerations and domains.
Eater
interface with theeat()
method, then as a client, you do not care that aHuman
implementing it has to first callwashHands()
andgetDressed()
, it's an implementation details of this class. If, as a client, you do care about this fact, then you're most likely not using the correct tool for the job.getDressed
before theyeat
, that is not the case for lunch. Depending on your circumstances,washHands();if !dressed then getDressed();[code to actually eat]
might be the best way to implement this for a human. Another possibility is what if other things require thatwashHands
and/orgetDressed
are called? Suppose you haveleaveForWork
? You may need to structure your program's flow to have it such that it's called long before that anyway.