Re: avoid cast to derived




Daniel T wrote:

This code, however, opens up the possibility
of the userUser::user2() method needing to be modified
when some other sub-type of Base is created
that userUser must treat differently as well.

Yes. The fact is not advantage of the desing way, but the
userUser:: code do not use private interface of userBase.

If we use only public interface of userBase, we can hope
to have nearly constant interface of userBase, as interface
of Base do.

The second disadvantage is theoretical unlimited growing
number of interfaces till total number of classes, but in
practical cases, we need new interface of derived very
rarely.

So, we do not make each class with his own interface, and
do not expect big number of interfaces, that is why, your
"possibility to be modified" we can not treat as obstacle
to get derived interface, if we need it.

There is another argument, that we can do not fear of
"possibility to be modified", becase the modified classes
developed together (see below).

The one acceptable use of dynamic_cast that we have talked
about is when it's "all or nothing" i.e., either the object
is the proper sub-type or the method doesn't deal with it
at all.

There are no resctrictions or reasons to do that. What is the
evident sence of the resctrictions? Nothing.

most of the problems in the code comes from the fact that
the "User" class is incomplete. It simply cannot stand on
its own, and needs a client to provide a Base object with
every message send

There are no resctrictions or reasons to minimizing number of
invokes of methods of external objects.

Any method, in general, encapsulates access to a state and
method is more abstracted than direct accsess to state,
and it does not matter who will provide method as access
to state.

And we can not consider class as state, it is much better
to do that as implementation of class's interface.

and using RCMs "Intelligent Child" pattern, we end up
with something like this:

Describe, please, the design pattern "Intelligent Child"
at least in three steps (context, goal, implementation).

'userUser' no longer needs to wonder if he has a userBase,
or some other sort of Base.

Of course, you are statically links the Base and User, but
your User class can not work with external Base, (later
developed, for example, which no need userBase interface),
see below.

Imagine a situation where User objects contain state
and Base objects contain state, and these states
interacted with each other ...

Understand.

... such that the client needed to know what
state each was in before passing a Base to a User.

Yes. But any upper level code, which is using some objects
of any classes, must know not only all its invoking methods
and parameters, but the exact sequence of methods to call.

For example, we must "open" file, "seek" to position and
"read" data of "size", and at each point we can lost state
or call "read" befor "seek".

Interface of any object can not encapsulate sequence or
parameters. If the sequence is hard or too many parameters,
we must do wrapper with more simple interface.

Well, HS Lahman has discussed this before, separate the
relationship instantiation from the method invocation.

I am still translating his post (too many new english
words and new terms), but for the first view I did not
see any obstacles to do the class design with
dynamic_cast<>.

Outcom:

I saw your objections, but found, that they not only do not
prohibit the design of classes, but has many disadvantages,
which were not listed by you.

1.
The first of disadvantage in your design is hard to
develop Base and User independently each from other.

The most used way in OO design - guess what can be changed
in future and encapsulating all that.

Dividing to Base and User has been done due to the condition.
Separated Base and User can easy be inherited independently

Base -> concreteBase1, concreteBase2, ...
User -> concreteUser1, concreteUser2, ...

Due to polymorphic interfaces any concreteBase and any
concreteUser can be linked each other at runtime and
class Creator encapsulates the behavior. Creator can easy
be inherited independently too.

Creator -> concreteCreator1, concreteCreator2, ...

The reason to have concreteCreator - to make concrete
pair (Base,User). Creator in fact do "dynamic inheritance"
of pair (Base,User).

You, of course, have divided the classes Base and User too,
but the reason of the dividing is not so easy to find.

Because your userUser can work only with userBase, but
separated Base and User must be able to work with any
derived from Base and User. This is the target of dividing.

I think that most desing patterns of classes can be
implemented with the help of separated classes, for
example bridge and factory can be implemented
exactly as example with dynamic_cast<>.

In other words, Base and User must be separated.

2.
Concerning dynamic_cast<>.

In most cases we no need any cast from Base to userBase,
due to polymorphic interface of separated classes.

But for perfomace reasons or any other reasons we can
extend interface of base class.

In oder to use extented interface we can make new
classes with new interfaces:

Base_new -> concreteBase_new1, concreteBase_new2, ...
User_new -> concreteUser_new1, concreteUser_new2, ...

But the classes is incompatible with already written
code, so we lost the reason of dividing Base and
User.

We can use adapter

Base-> Base_adapter(Base_new)
User-> User_adapter(User_new)

or just inherit new interface from old

Base-> Base_new
User-> User_new

Now new code can use advantages of new interface, and
old code still can work, but already without advantages
of new interface, so we lost the reason of dividing
Base and User againg.

At this point all depends only from concrete conditions,
and concrete classes.

But in general I do not see any obstacles, if implemented
in derived methods of base classes will switched to new
interface if it is possible. In other words, will do
dynamic_cast<>-depended code.

Using dynamic_cast<> allows some previously separated
classes ( but developed together for cooperative work
for any reasons, and linked via pointer to its base
class) use its extended interfaces.

Dynamic_cast<> allows to make concrete pair (Base,User)
at runtime in each call, hide the creation from all
other parts of program.

3.
One can see, that dynamic_cast<> acts as if-else
operator. Can compiler do the if-else?

I heard that exists OO languages with more than one
"virtual condition", if C++ allows do more then one
dispath per method, then yes.

Borland C++ 3.x was able use int as second dispath
selector (with many limitations). In our case,
instead of int we must use type of parameter
as second dispath selector.

//for all obj do obj.method();
void user::user2(Base& obj)[*]{ obj.method(); }

//for obj == Base_new&
void user_new::user2(Base& obj)[Base_new& obj]{ exit(); }
//for all other obj do obj.method();
void user_new::user2(Base& obj)[*]{ obj.method(); }

or we must use dynamic_cast<>

Dynamic_cast<> allows to have separated classes for
development and joined classes for usage.

There are many cases of improper usage of
dynamic_cast<>.

I you have any objections to me, i will be glad to see them.

.



Relevant Pages

  • Re: CoBOL moved to OO
    ... reasons, such as not wanting to learn it, or being threatened by it. ... I love the WSIWYG interface in my word processor, ... This insane attitude can be stated ... Several local disasters are better than industry ...
    (comp.lang.cobol)
  • Re: Creating a multi-tier client/server application
    ... I was really hoping to avoid an entirely web-based app, ... Some reasons for them would be (in no ... what the user interface should work/look like. ... you've never had to deal with use cases, consider yourself a lucky, ...
    (comp.lang.python)
  • Re: Is it possible to manually activate an eth0 connection?
    ... different reasons. ... Packages like 'emacs' and 'midnight commander' are not yet available, ... do you see any interface as up when you ... network manager to change the connection to eth1. ...
    (Ubuntu)
  • Of Interest to Webmasters and HTML Programmers
    ... I always thought I could "sell" MY interface to this company, ... Now I can send them a demo, of what I can do, without fear of losing ... (IT has a VERY Simple index for demo reasons, ...
    (comp.sys.cbm)