I’m working on a design of an object that changes its behavior based on its state. One if its properties holds an object that can be of various types. Here’s an example:
class Person {
// many types of glasses available
protected $glasses;
public function putOnBoots ()
{
// does this type check smell?
if ($this->glasses instanceof SunGlasses) {
trigger_error('never wear boots with sunglasses');
return false;
}
// [...] put on boots
return true;
}
public function lookAtStuff ($stuff)
{
// glasses provides polymorphic behavior here
return $this->glasses->filter($stuff);
}
}
It should be noted that $glasses does provide its own polymorphic behavior elsewhere in the class so the types serve a bigger purpose. But there are some behaviors (like putOnBoots()) that don’t feel like they should belong to $glasses, even though they might be impacted by its type in how it indicates the state of Person.
Something about checking an object type in this way feels wrong to me. Do I detect an odor, or am I just imagining things?
It does seem a bit smelly to me. A better option would be to use some polymorphic behavior of the glasses. Perhaps a virtual method like…
that returns TRUE in most cases, but for sunglasses returns FALSE.
The advantage is that you can extend the code by adding other types of glasses, and they can decide on their own whether they “go with boots” or not – and you don’t have to worry about whether you need to modify your putOnBoots() method every time you add another type of glasses.