Click to See Complete Forum and Search --> : Nested Class Inheritance
alumb
November 29th, 2004, 01:00 PM
ok, so I am trying to inherit a nested set and overide a few functions it.
public class tree {
public Node myNode;
public void buildNode() {
myNode = new Node();
}
public class Node {}
}
public class usertree : tree {
public class Node : tree.Node {
int i;
public Node() { i = 5; }
}
}
usertree T = new usertree();
t.buildNode();
when I do this T.buildNode calls the constructor of the tree.Node class, not the usertree.Node class... is it possible to get it to call the later? something like a virtual class? (for note: In the actual application there is alot more in the buildNode function so I don't want to simply duplicate it into the usertree class.)
Thanks.
Mr. Tomaszek
November 29th, 2004, 01:55 PM
I really don't understand you. In your sample t.buildNode() will call buildNode() from tree class which will call constructor of Node class
alumb
November 29th, 2004, 02:04 PM
sorry... I will attempt to be clearer.
when T is an instance of the usertree class I need the "new Node()" function to call the constructor of the usertree.Node class, rather than the tree.Node class. If possible the behaviour would be similar to how a virual / override function works: The tree.Node class would be declared virtual and the usertree.Node class would override it. Unfortunatly it does not appear that c# alows virtual nested classes.
AnotherAlias
November 29th, 2004, 02:16 PM
You REALLY do not want to do this. The is no practical, understandable, extensible way to inherit a nested class. This is one of the reasons that nested classes are strongly discouraged (use namespaces to segment it out instead). The (supposed) benefits of tighter access control are far out weighted by the complexities of this type of construct...
alumb
November 29th, 2004, 02:24 PM
ok, maybe with a little more background another solution can be found.
the buildNode function reads in data from a database and produce a tree out of it. Most of the time this tree is fairly general, but in a few instances the tree needs to be specific to a particular user of the system. So I produced the usertree class which inherits from the tree class and adds fields for things like username. Each node in the extended tree also need to store additional data about "completeness" of the node, hence the extended node class. Now, the buildNode function is rather long and the "new Node()" calls are right in the heart of it, so I don't want to have to re-write the function in the usertree class. How can I get the calls to "new Node()" to invoke instances of the extended node class rather than the base one?
Mr. Tomaszek
November 29th, 2004, 02:32 PM
Well, I got your point.
public class tree
{
public usertree.Node myNode;
public void buildNode()
{
myNode = new usertree.Node();
}
public class Node
{
public Node()
{
}
}
}
public class usertree : tree
{
public usertree()
{
}
public class Node
{
int i;
public Node()
{
i = 5;
}
}
}
note also that usertree.Node is hiding inherited tree.Node member
alumb
November 29th, 2004, 02:57 PM
hmm...
When the tree class is invoked directly myNode still needs to be of type tree.Node, it is only when the usertree class is invoked that myNode needs to be of type usertree.Node. Maybe my inital code was too simplified, here is something more approximating my situation:
public class Tree : webControl {
// initalization code
buildNodes() {
//get data from databas
foreach(row in dataset)
this.controls.add(new Node(row));
}
public class Node {
public Node(datasetrow r) {
//some code that sets the nodes properties
}
}
public class userTree : Tree {
public string username;
//initalization code
public class Node : Tree.Node {
public bool completed;
public Node(datasetrow r) : base(r) {
//code that sets user specific nodes properites
}
}
}
Tree t = new Tree();
t.buildNodes(); // builds tree with nodes of type Tree.Node
userTree U = new userTree();
U.buildNodes(); // currently builds tree with nodes of type Tree.Node, should build tree with nodes of type userTree.Node.
AnotherAlias
November 29th, 2004, 03:29 PM
Assuming you are in control of the base and derived classes, I would....
1) Make the node classes NOT be nested classes.
2) You a factory to product the nodes, not direct constructor calls
3) Create a factory for TreeNodes in the UseTree constructor.
4) Create a factory for UserTreeNodes in the UserTree constructor.
A more generic (and common) approach is tu just have a (void *) member in the base (and only) Node class. The base treeswill not use this member but the UserTrees can initialize it with an instance of "UserNodeAdditionalData".
Mr. Tomaszek
November 29th, 2004, 04:01 PM
myNode still needs to be of type tree.Node
Sorry, you can't do this. You may create a NodeBase class and drive from it tree.Node and usertree.Node classes. Than you can cast to type needed.
I'm agree with AnotherAlias - better not to use such complex structs
alumb
November 29th, 2004, 04:14 PM
Sorry, you can't do this. since userTree.Node is derived from the Tree.Node class I belive this is possible.
Assuming you are in control of the base and derived classes, I would.... this is a good suggestion, it does mean some signifigant amount of extra work... I would have to duplicate all of the Node class constructors, of which there are currently 5, in the Tree class. This would also have to be done in the userTree class, and any future class that changed the default node class.
AnotherAlias
November 29th, 2004, 04:19 PM
this is a good suggestion, it does mean some signifigant amount of extra work...
Compared to the amount of time you have spend, are spending and will spend on the current approach, I am willing to wager it will become less work in the very short run.
alumb
November 29th, 2004, 04:32 PM
Compared to the amount of time you have spend, are spending and will spend on the current approach, I am willing to wager it will become less work in the very short run.
haha, quite possibly. I guess it depends on how many classes end up being derived from the node class, I really have no idea at this point. This is going to be part of a library of tools, so I guess I was trying to make it look nice. I am going to try some reflection voodoo, but will probably just end up using your suggestion.
Thanks for your help.
Krzemo
November 29th, 2004, 10:53 PM
How can I get the calls to "new Node()" to invoke instances of the extended node class rather than the base one?
But there are no "virtual" and "override" keywords in your code.How do you expect that it should work without it :) ?
Solution is very simple. U need only replace "new" operators in your code (class Tree) with calls to virtual GetNewNode() method and override GetNewNode() in derived class.
Bellow is simplified example:
public class Tree
{
public Tree()
{
}
public void BuildNodes()
{
//Node nd=new Node();
Node nd=GetNewNode();
}
public virtual Node GetNewNode()
{
return (new Node());
}
public class Node
{
public Node()
{
System.Windows.Forms.MessageBox.Show("Tree.Node");
}
}
}
public class userTree:Tree
{
public userTree()
{
}
public override Tree.Node GetNewNode()
{
return (new Node());
}
public new class Node : Tree.Node
{
public Node() : base()
{
System.Windows.Forms.MessageBox.Show("userTree.Node");
}
}
}
Hope it helps.
Best regards,
Krzemo.
Norfy
November 30th, 2004, 02:23 AM
Alternatively move the constructor code into virtual methods...public class Tree
{
public class Node
{
public Node(Row row)
{
Initialize(row);
}
protected virtual Initialize(Row row) {...}
}
}
public class UserTree : Tree
{
public class Node : Tree.Node
{
public Node(Row row) : base(row) {}
public override void Initialize(Row row)
{
// this will be invoked from the base class
}
}
}
codeguru.com
Copyright Internet.com Inc., All Rights Reserved.