Re: dynamic_cast is ugly!
On 13 Mar, 09:14, Nick Keighley <nick_keighley_nos...@hotmail.com>
wrote:
On 12 Mar, 12:23, dave_mikes...@fastmail.fm wrote:
On Mar 12, 6:38 am,Nick Keighley<nick_keighley_nos...@hotmail.com>
wrote:
On 12 Mar, 10:45, "Daniel T." <danie...@earthlink.net> wrote
Juha Nieminen <nos...@thanks.invalid> wrote:
Daniel T. wrote:
Juha Nieminen <nos...@thanks.invalid> wrote:
It's not really that you need dynamic cast to *know* if the
shape is a Square. In this case you need it if you want to *do=
*
something to the object if it's a Square, and this operation i=
s
not supported by Shape, only by Square.
And therein lies the problem. "you want to *do* something to the=
object if it's a Square". If you find yourself in that situation=
,
the design has already slid downhill. IMHO.
And what is the alternative you propose?
Don't try to *do* things to objects. Objects are supposed to do for
themselves, clients *notify* the objects of things, they don't order=
them around.
I can only think of one possibility: Clutter the 'Shape' base clas=
s
with Square-specific virtual functions. This defies all good OO
design.
What is it you are trying to tell squares that you don't want any ot=
her
shapes to know about? Why the big secret?
"colour all the squares yellow"
If the shapes example is a bit fanciful make it a UML editor.
I want all the interfaces to stand out by changeing their
colour and my model is huge.
"colour all the interfaces yellow"
You can solve that by putting homogeneous elements in their own
container for just such operations If you want to globally change the=
line style of connectors, operate on the Connector collection, don't
rifle through the generic one interrogating each object
apply (set_to_yellow_func, all_squares_collection);
Is what I was thinking about this. But then I thought
how do I generate ASC without a dynamic cast.
forall drob in all_drawable_collection
Square* square = dynamic_cast<Square*>drob;
if (square != 0)
all_squares_collection.add(square);
I suppose the answer is to generate it in parallel
with ADC. If I add (or remove) a square to ADC then
I add (or remove) it to ASC.
ok. sorry to be banging on about this.
Lets use my (slightly) more real world example. A UML editor
where there is a requirement to apply operations only to
certain elements.
// almost C++
Ui::hiliteAllInterfaces()
{
apply (colour_item_yellow, all_interfaces_collection);
}
So I was wondering where all_interfaces_collection came from.
It could be generated when needed from a collection of all
drawable objects. But that involves a dynamic cast.
So it could be generated as a side effect of updating
all_drawable_collection(). Code to add a new element
looks like this
// the users adds a drawable object to the current picture
Ui::add_object()
{
Drawable* d = drawable_factory.create(curr_object_type);
picture->add_object(drawable_factory.create(curr_object_type)));
}
Drawable* DrawableFactory::create (DrawableType t)
{
switch (t)
{
case CLASS_TYPE:
return new DrawableClass();
case INTERFACE_TYPE:
return new DrawableInterface();
}
}
Now how to update the subclass collections. These are shown as deltas
from above
//// option A
//// add to each collection
Ui::add_object()
{
Drawable* d = drawable_factory.create(curr_object_type))
picture->add_object(d);
switch (curr_object_type)
{
case CLASS_TYPE:
all_classes.add_object(d)
case INTERFACE_TYPE:
all_interfaces.add_object(d)
}
}
// BLETCH. two switch statements.
// brittle hard to modify code
//// option B
//// move more into factory
Ui::add_object()
{
drawable_factory.create(curr_object_type)
}
Drawable* DrawableFactory::create (DrawableType t)
{
Drawable* d;
switch (t)
{
case CLASS_TYPE:
d = new DrawableClass();
all_classes.add_object(d)
case INTERFACE_TYPE:
d = new DrawableInterface();
all_interfaces.add_object(d)
}
return d;
}
// the factory seems a bit "busy"
// option C
// move more into subclass
DrawableClass::created()
{
all_classes.add_object(this)
}
Ui::add_object()
{
Drawable* d = drawable_factory.create(curr_object_type))
picture->add_object(d);
d->created();
}
at least this follows the OCP! The drawable objects now know
they are held in collections. Is this bad? Could the collection
management be moved somewhere else?
<snip>
--
Nick Keighley