简体   繁体   中英

Create a derived class object from a base class object

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.

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.

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.

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.

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.

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 (ie 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).

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM