I understand what you're recommending, and I've seen Bob Martin talk about it extensively (polymorphic dispatch instead of instanceof), but it's something I disagree with.
To do this kind of polymorphic dispatch, objects have to deal with multiple concerns within themselves.
In a video game, a Car might have .render(), .collide(), .playSound(). Later on you can add a Dog, which also has those three methods, and you don't need to edit/recompile the Renderer, the PhysicsEngine, and the SoundEngine. And other programmers can add additional entities like this without introducing bugs into my precious code! What's there not to love?
Well, now both my Car and my Dog need to know about graphics, physics, and sound. And these entities don't exist in isolation. Cars and Dogs need to be rendered in the right order (maybe occluding one another). They'll definitely need to check for collisions with each other. And (something which has actually happened to me in a Game Jam) my sound guy is going to need to step into all my objects to add their sound behaviours.
I would much rather work in the Physics.collideAll() method, and have it special-case (using instanceof) when I'm thinking about physics, and work in the Graphics.renderAll() method when I'm thinking about graphics.
A more common example I see in day-to-day backend Java web dev: when I'm sitting in the (REST) Controller deciding how to convert my Java objects into HTTP responses, I much prefer it if I can consider them all in one method, and map out {instanceof Forbidden} to 403, {instanceof NotFound} to 404, etc., rather than putting getCode() (and other REST-specific stuff) into the Java classes themselves.
PhysicsEngine {
List<Entities> entities;
doCollisions() {
// Delegate to whomever.
entities.forEach(e -> e.collide());
}
}
Dog {
collide() {
// What the hell can I do here?
// I don't know about the rest of the world
}
}
Car {
collide() {
// What the hell can I do here?
// I don't know about the rest of the world
}
}
Worse way:
PhysicsEngine {
List<Entities> entities;
doCollisions() {
// Delegate to whomever.
entities.forEach(e -> e.collide());
}
}
Dog : PhysicalObject {
collide() {
super.collide();
}
}
Car : PhysicalObject {
collide() {
super.collide();
}
}
PhysicalObject {
collide() {
// Not only do I not know about the rest of the world
// I don't even know how *I* collide, because what am I?
}
}
To do this kind of polymorphic dispatch, objects have to deal with multiple concerns within themselves.
In a video game, a Car might have .render(), .collide(), .playSound(). Later on you can add a Dog, which also has those three methods, and you don't need to edit/recompile the Renderer, the PhysicsEngine, and the SoundEngine. And other programmers can add additional entities like this without introducing bugs into my precious code! What's there not to love?
Well, now both my Car and my Dog need to know about graphics, physics, and sound. And these entities don't exist in isolation. Cars and Dogs need to be rendered in the right order (maybe occluding one another). They'll definitely need to check for collisions with each other. And (something which has actually happened to me in a Game Jam) my sound guy is going to need to step into all my objects to add their sound behaviours.
I would much rather work in the Physics.collideAll() method, and have it special-case (using instanceof) when I'm thinking about physics, and work in the Graphics.renderAll() method when I'm thinking about graphics.
A more common example I see in day-to-day backend Java web dev: when I'm sitting in the (REST) Controller deciding how to convert my Java objects into HTTP responses, I much prefer it if I can consider them all in one method, and map out {instanceof Forbidden} to 403, {instanceof NotFound} to 404, etc., rather than putting getCode() (and other REST-specific stuff) into the Java classes themselves.