Reputation: 4782
in my application I have a tree-like data structure. The nodes are of class X. I have another class Y which is derived from X. Eventually, I need to "transform/change" the nodes from type X to type Y - in the whole tree structure.
Is there an easy way to do this or do I have to parse the whole tree, recreating it by instantiate each node with type Y?
Thanks in advance,
Frank
Edith says: Thanks for all your answers! I try to explain, why I need this behavior:
Let's imagine, we are a caterer. We want to model our portfolio in a tree. One node could be "soups" and we offer potato soups, tomato soups and noodle soups - each one is a child node of the "soups" node. After finishing the modeling, we present the tree to a customer who choses the "basic catering service". That means that she can chose one of the soups for her dinner.
For my underlying model, that means I need an additional field "IsSelected", which I do not need, when the caterer creates the portfolio. So I want to derive class Y from class X with the additional field.
Upvotes: 1
Views: 2414
Reputation: 49965
Because no-one has yet pointed this out...
If you create an object as Y
it can be cast to X
and then back to Y
again, but an object created as X
cannot be cast to Y
. This is just basic OO behaviour.
This means if you create your datasource as a hierarchical list of Y
, you can then cast them to X
, and then back to Y
when it suits.
In fact, if you are using Linq, there is an extension method called Cast() on the Enumerable class. You can use it like this:
public class Animal { }
public class Dog : Animal { }
List<Dog> dogs = new List<Dog>();
List<Animal> animals = dogs.Cast<Animal>().ToList();
You haven't mentioned what you are using (WinForms/WPF/Silverlight/ASP.NET), but WPF has a HierarchicalDataTemplate that you can bind to a list that is node like (i.e. each item in the list can have children). Using something like this with the Cast()
from above should work nicely.
Of course this doesn't mean that you shouldn't review your code and see if this is really the best way to do it (as others have also said).
Upvotes: 0
Reputation: 273784
Yes, you will have to traverse the whole tree and re-create all the nodes.
Which makes it a good idea to reconsider the design that led to this situation.
Upvotes: 2
Reputation: 7340
Maybe implicit or explicit operator cast can help you, but I think some bad design lead to this:
public static implicit operator MyTypeB( MyTypeA a ) {
MyTypeB b = new MyTypeB();
// copy all a properties
return b;
}
People say that you would need to loop and recreate all nodes, but this way all nodes can be used as different type nodes because they do the work of recreating when needed.
But please note that cast operator overloading should not be used if some data is lost.
And seriously it all leads to the assumption that you are missing an Interface for those node types, and that the collection should be a collection of this Interface type.
Upvotes: 0
Reputation: 11513
Changing the type of an object is usually a big code smell. If this is required because some part of the object's behaviour should change, have a look at the Strategy Design Pattern.
But anyways you would usually have to traverse the whole tree to change the strategy on each node. Iff really all objects should change the behaviour, you could also think about a combination with the Flyweight Design Pattern. But as already mentioned, there is too few information to give a good advice here.
Upvotes: 0
Reputation: 26792
The actual type of an object is determined when it's constructed and can not be changed afterwards. So no, there is no other way.
Upvotes: 1