Re: Visitor, dynamic_cast or ...

From: H. S. Lahman (h.lahman_at_verizon.net)
Date: 10/26/03


Date: Sun, 26 Oct 2003 18:00:49 GMT

Responding to Harris...

>>When OcTree.Find returns a Leaf, that effectively instantiates the
>>[Client]/[Leaf] relationship. So [Client] does not know that
>>[Internal] nodes even exist.
>>[...]
>>This yields a fairly simple and efficient view of the tree that doesn't
>>require complexities like Visitor, nastiness like dynamic_downcast, or
>>god classes. However, that is only accomplished by separating the
>>concerns of tree navigation from leaf processing (i.e., by implementing
>>and navigating a second relationship).
>
>
> What does that mean in practice? What type does OcTree.Find return? How do
> we turn that result into a Leaf<int> node, or a Leaf<String> node, or
> whatever kind of leaf node it happens to be?
>
> I agree that the client doesn't need to know about InternalNode, but that
> is only a small part of the problem. The bigger part is not knowing what
> kind of leaf node we have.

See also my recent response to Daniel T. As I indicated, one way to
deal with that is an attribute like Node.isLeaf. OcTree.Find /always/
returns a Leaf. /When/ it returns is determined by a combination of
Node.isLeaf and the key evaluation that ensure the instance in hand is,
indeed, a Leaf.

This is really an implementation issue and there are lots of ways to
implement the relationships. For example, we might implement node
navigation by emulating dynamic_downcast via:

class NodePtr
{
private:
     bool isLeaf;
     Object* node;

public:
     bool getIsLeaf () {return this.isLeaf;}
     Leaf* getLeaf() {return (Leaf*) node;}
     Internal* getInternal() (return (Internal*) node;}
}

I would not usually recommend this sort of thing for manual elaboration,
but it is perfectly safe for automatic code generation because
NodePtr.isLeaf is initialized properly by the code generator so
getIsLeaf and, subsequently, getLeaf can be invoked safely by
OcTree.Find in all cases.

[To put it another way, that Node.isLeaf is true when and only when the
instance is a Leaf is enforced when the relationship is instantiated.
NodePtr is just a mechanism for implementing the relationship so that
the client knows what type it will have in hand prior to actually
accessing it. That mechanism just provides a safe, orthogonal means for
OcTree to navigate to either specialization directly; in effect the
client chooses the direct relationship to navigate.]

Note that if one implements this way and object code size is not an
issue, then subclassing can be completely eliminated at the OOP level.
One can then use a variation on Daniel T.'s solution by defining [Node] as:

class Node
{
private:
     NodePtr* (links)[8]; // navigation; NULL entries for Leaf
     Data* data; // NULL for Internal; the specialization
                           // is in its own unique object.
public:
     getNodePtr(int n) {return links[n];}
     getData() {return data;}
}

That allows the Client to do the right thing by simply checking the
conditionality of the relationships. A better approach is to have the
Client always accesses a Node through a NodePtr. Then Client knows
prior to access how to handle the instance. That is, Client can
dynamically select the relationship to be navigated.

>
>
>
>>So one can use a simple type attribute to distinguish [Leaf] vs.
>>[Internal] for navigation purposes.
>
>
> So we have something like an isInternal() function followed by a
> static_cast? Or an asInternal() method as I suggested in my other post? Or
> what? How do we actually solve the problem?
>
> I'm sorry, but I just don't see how your analysis answers the question
> being asked, namely, how to get from a base class pointer to a more
> specific one.

It doesn't. I am arguing that one should not try to do that at all. If
one needs a specialization, then one should navigate a relationship
directly to that specialization rather then going through the base
class. So /any/ attempt to access a specialization through its
generalization is symptomatic that some necessary relationship has been
omitted in the OOA/D.

*************
There is nothing wrong with me that could
not be cured by a capful of Drano.

H. S. Lahman
hsl@pathfindermda.com
Pathfinder Solutions -- Put MDA to Work
http://www.pathfindersol.com
(888)-OOA-PATH



Relevant Pages

  • Re: Page Load event is called....
    ... > the life cycle of every page, ... > instructing it (the client) to open a different page instead of the one ... > server and skips the additional HTTP request but neither method will ... >> always happen when I navigate to the next page. ...
    (microsoft.public.dotnet.framework.aspnet)
  • Re: Downcasting - whats the problem?
    ... > Responding to Developer... ... >> I would like to ask what will be a very basic question for many on ... there is no to/from to navigate. ... > However, if a Client must access the doAresponsibility, it can't do ...
    (comp.object)
  • Re: Downcasting - whats the problem?
    ... > I would like to understand what the real problem is with downcasting ... there is no to/from to navigate. ... That is, Client ... However, if a Client must access the doAresponsibility, it can't do ...
    (comp.object)
  • Re: Cannot access Previous versions from Win2K
    ... I rolled the previous versions client to all of our clients and then checked ... that the previous versions tab appears when the user right clicks on a file ... My problem is that when i navigate to a file using win2000 SP4 which has ... >> If i navigate to the same place on an WinXP client the folders appear.. ...
    (microsoft.public.windows.server.general)