What you describe is perfectly possible and commonly known as "Decorator Pattern".
Link-Only answers are bad, I will elaborate later when I have more time.
Meanwhile, Wikipedia has more Info: Decorator Pattern.
1 Cat cat = new Cat();
2 Animal pet = new Pet(cat, "Foo");
3 if (pet instanceof Pet){
4 if (pet.kind instanceof Cat){
5 Pet.sayMeow();
6 }
7 }
This has the disadvantage that you need to use instanceOf
. Usually, you would have your Animal
class have a method - let's call it makeNoise
. Probably abstract. You Animal-Implementations ( Cat
, Dog
... ) then would override that method to make their respective noise ("Bark","Miow" ...).
In the snippet, it seems only Pets can make noises ... that makes it a little bit more complicated because there would be various ways to do that.
You could have the decorator save a sound and override the makeNoise to make that sound. Like so:
Cat catInstance = new Cat();
catInstance.makeNoise(); // Default impl: NOP => "" - no sound.
Animal pet = new Pet( catInstance, "Mieow" );
pet.makeNoise(); // => "Mieow"
The point of all this is: You want to avoid using instanceof
. You don't care if the Animal is a Cat a Dog, a Pet-Cat or a Pet-Dog. They shall make their correct sounds if and when told to. So you could have a Collection of "Animal"s and tell them all to "makeNoise" and each will remain silent, bark or mieow without you having to care for if they are pets or which specific child of Animal
.
EDIT: Reading my answer again, it is more like a Policy (Strategy pattern) than a Decorator.
The Policy changes how something is done, while the Decorator would add the feature.
So to be a true Decorator, it would mean that makeNoise
would be in the interface of Pet
. Which means you couldn't call that method on Animals.
That is why I change my suggestion from "Decorator" to "Strategy" pattern.
The example above still holds. You would kind of have a "default" Strategy and inject the "Pet"-Strategy by using a Decorator-Like implementation approach.
Of course all of this could also be done differently to implement the pattern more strictly.
At last, if( x instanceof X) ...
always jingles the "Visitor"-Bell, too.