OOP question: Is upcasting ok in this situation?
If I'm not mistaken, general OOP wisdom says that upcasting should
usually be avoided if possible. I have a situation, however, where I
can't think of a better way than upcasting for this specific solution.
I was wondering if there exists a "standard" solution to this which
avoids the upcasting and does it more cleanly.
Assume that we have, for example, some kind of container/editing class
named PrimitiveEditor which handles objects of (the abstract) type
Primitive. So you can have, for example, classes like:
class Circle: public Primitive { ... };
class Square: public Primitive { ... };
etc.
The PrimitiveEditor defines a callback interface, let's call it
PrimitiveHandlingCallback, and it's used, for example, like this:
class MyClass: public PrimitiveHandlingCallback
{
PrimitiveEditor editor;
std::list<Circle> circles;
std::list<Square> squares;
public:
MyClass(): editor(this) {}
// Derived from PrimitiveHandlingCallback:
virtual void doSomethingToPrimitive(Primitive*);
};
Now, each time MyClass creates an instance of Circle or Square (into
the correspondent list) it gives a pointer to that instance to the
editor. The editor is called to handle those objects. The editor may
call the doSomethingToPrimitive() function so that MyClass can handle
the primitives in whatever special way it needs to.
And this is where my question raises. Is it ok to do it like this:
void MyClass::doSomethingToPrimitive(Primitive* p)
{
Circle* circle = dynamic_cast<Circle*>(p);
if(circle)
{
// Do something with circle, specific to the type Circle
return;
}
Square* square = dynamic_cast<Square*>(p);
if(square)
{
// Do something with square, specific to the type Square
return;
}
}
Is there any better/cleaner way of doing this same thing without
having to upcast?