Inheritance Design Question

M

Mike

I want to provide an abstract class to derive all nodes from. In the example
below Parent in the base class is of Type Node, but in the custom class I
want Parent to return a Type CustomNode. When CustomNode is accessed by a
helper class as Node Parent is always null. Is this a poor design, Im sure
it's a common problem and I am just missing something.

Note: I use virtual for Parent because abstract will not compile.

public abstract class Node
{
public virtual Node Parent
{
get { return null; }
}
public virtual bool IsLastChild
{
get { return this._isLastChild; }
}
private bool _isLastChild = false;
}

public class CustomNode : Node
{
public new CustomNode Parent
{
get { return this._customNode; }
}
private CustomNode _customNode = null;
}
 
T

Thomas P. Skinner [MVP]

You need to use override rather than new in the derived class.

Thomas P. Skinner [MVP]
 
M

Mike

Override does not work when changing the return Type, I want to return
CustomNode which derives from Node.
 
D

David Browne

Mike said:
Override does not work when changing the return Type, I want to return
CustomNode which derives from Node.

You really should return Node. You are free to cast it to CustomNode if you
know it is a CustomNode.

David
 
N

Nick Malik

Your design problem is not clear. I understand what you are trying to do,
but not why, so it is difficult to help.

It is clear that a node has a parent. It is not clear why a childnode would
need to return anything except a node type for its parent, because this
restricts the entire tree that you can describe.

What design pattern are you attempting to implement? Can you do this using
the Visitor pattern? (http://home.earthlink.net/~huston2/dp/visitor.html)

--- Nick
 
M

Mike

Since CustomNode is a Node, then any code expecting a node has a Node, but
other code written for CustomNode gets a CustomNode, and no casting is
needed. If there is a way to redesign these classes to work without casting
I am al for it as it will reduce runtime errors associated with casting.

It seems odd that the CustomNode #1 below works, because the compiler knows
that _customNode is a Node, but #2 does not, when CustomNode derives from
node. I cannot imagine any situation where #2 would cause a problem.
--What am I missing here?

#1) Works:

public class CustomNode : Node
{
public override Node Parent
{
get { return this._customNode; }
}
private CustomNode _customNode = null;
}

#2) Does Not Work:
public class CustomNode : Node
{
public override CustomNode Parent
{
get { return this._customNode; }
}
private CustomNode _customNode = null;
}
 
M

Mike

Nick,

Consider that CustomNode has:

public string Description
public string GetParentDecriptions(CustomNode node)
{
// loop node parents and return a string containing all parent
descriptions
}
 
D

David Browne

Mike said:
Since CustomNode is a Node, then any code expecting a node has a Node, but
other code written for CustomNode gets a CustomNode, and no casting is
needed. If there is a way to redesign these classes to work without
casting
I am al for it as it will reduce runtime errors associated with casting.

It seems odd that the CustomNode #1 below works, because the compiler
knows
that _customNode is a Node, but #2 does not, when CustomNode derives from
node. I cannot imagine any situation where #2 would cause a problem.
--What am I missing here?

You are correct, there's no reason why it couldn't be made to work. It just
doesn't happen to.

The feature is called "covariant return types". Java 5 and C++ and various
other OO languages support it. .NET does not.

David
 
D

David Browne

Mike said:
Nick,

Consider that CustomNode has:

public string Description
public string GetParentDecriptions(CustomNode node)
{
// loop node parents and return a string containing all parent
descriptions
}

For this, you can just access the private member _customNode. You aren't
limited to to the virtual accessor when implementing methods on the type.


public string GetParentDecriptions(CustomNode node)
{
StringBuilder sb = new StringBuilder();
CustomNode parent = node._customNode;
while (parent != null)
{
sb.Append(parent.Description);
parent = parent._customNode;
}
return sb.ToString();

}

David
 
M

Mike

David,

Would you say in this case, the proper solution would be to provide...

public CustomNode CustomNodeParent

....this seems like the only way to avoid casting, but it feels clunky and
maybe there is another way, or this is a poor design.
 
M

Mike

Good point, but another class ( CustomNodeWriter ) that does not have
private or protected access needs to navigate a CustomNode tree Parent will
have to return a Node and I am back to casting. It seems that adding: public
CustomNode CustomParent, is the only real solution here.
 
D

David Browne

Mike said:
David,

Would you say in this case, the proper solution would be to provide...

public CustomNode CustomNodeParent

...this seems like the only way to avoid casting, but it feels clunky and
maybe there is another way, or this is a poor design.

If CustomNode is an important subclass, that's what I would do.

The other solution is to switch node to an interface and use explicit
interface implementation for the parent method. Then you are free to
implement subtype-returning Parent methods on each subclass. I'm not sure
that's a better solution, though.


David
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top