La respuesta es bastante simple.
¿Cómo manejar objetos que pueden hacer más de lo que esperas?
No necesita manejarlo porque no serviría para nada. Una interfaz generalmente se diseña dependiendo de cómo se vaya a usar. Si su interfaz no define lavarse las manos, entonces no le importa como interlocutor; si lo hubiera hecho, lo habría diseñado de manera diferente.
Por ejemplo, en caso de que sea la hora de la mañana y si se trata solo de un animal, se llama comer, de lo contrario, si es un humano, llame primero a washHands, getDressed y solo luego llame a eat. ¿Cómo manejar estos casos?
Por ejemplo, en pseudocódigo:
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(); }
}
Ahora lo implementa IMorningPerformer
para Animal
simplemente comer, y Human
también lo implementa para lavarse las manos y vestirse. La persona que llama de su método MorningTime podría importarle menos si es humano o un animal. Todo lo que quiere es la rutina matutina realizada, que cada objeto hace admirablemente gracias a OO.
El polimorfismo muere.
O lo hace?
Necesitas averiguar el tipo de objeto
¿Por qué están asumiendo eso? Creo que esto podría ser una suposición errónea.
¿Existe un enfoque común para manejar estos casos?
Sí, generalmente se resuelve con una clase o jerarquía de interfaz cuidadosamente diseñada. Tenga en cuenta que en el ejemplo anterior no hay nada que contradiga su ejemplo tal como lo ha dado, sin embargo, probablemente se sentirá insatisfecho, porque ha hecho algunas suposiciones más que no escribió en la pregunta al momento de escribir. , y estos supuestos son probablemente violados.
Es posible ir a una madriguera de conejos ajustando sus suposiciones y modificando la respuesta para satisfacerlas, pero no creo que sea útil.
Diseñar buenas jerarquías de clases es difícil y requiere mucha información sobre su dominio comercial. Para dominios complejos, uno pasa por dos, tres o incluso más iteraciones, ya que refinan su comprensión de cómo interactúan las diferentes entidades en su dominio comercial, hasta llegar a un modelo adecuado.
Ahí es donde faltan ejemplos simplistas de animales. Queremos enseñar de manera simple, pero el problema que estamos tratando de resolver no es obvio hasta que profundice, es decir, tenga consideraciones y dominios más complejos.
Eater
interfaz con eleat()
método, entonces, como cliente, no le importa que unaHuman
implementación tenga que llamar primerowashHands()
ygetDressed()
es una implementación de detalles de esta clase. Si, como cliente, le importa este hecho, lo más probable es que no esté utilizando la herramienta correcta para el trabajo.getDressed
anteseat
, ese no es el caso para el almuerzo. Dependiendo de sus circunstancias,washHands();if !dressed then getDressed();[code to actually eat]
podría ser la mejor manera de implementar esto para un ser humano. Otra posibilidad es ¿qué pasa si otras cosas requieren esowashHands
y / ogetDressed
se llaman? ¿Y si tienesleaveForWork
? Es posible que necesite estructurar el flujo de su programa para tenerlo de modo que se llame mucho antes de eso de todos modos.