views:

124

answers:

1

Hi Guys,

I have a tree structure design problem, and i can't think of a way out.

i want to have one class Tree containing a generic data, and extend the Tree class with ComplexTree that will contain more methods like Iterate, DoSomthingOnComplex, etc.

here is a sample of the code i have:

class Tree<TData>
{
    public TData Data { get; set; }
    public ICollection<Tree<TData>> Children { get; private set; }

    public Tree<Data>(TData data)
    {
         // ...
    }

    public void Iterate(Action<TData> action)
    {
         action(Data);  
         Children.ForEach(x => x.Iterate(action));
    }
}

class ComplexTree<TData> : Tree<TData>
{
    public int ComplexValue1 { get; set; }
    public int ComplexValue2 { get; set; }

    public ComplexTree(TData data, int cv1, int cv2)
        : base(data)
    {
         // ...
    }

    public void DoComplexStuffOnTree()
    {
         // ... might want to use the base methods here
    }
}

problem is that for one thing, i can't really expose the collection that holds Tree to anyone that has create ComplexTree and i can't use Iterate for the ComplexTree because i can't use the cv1, cv2 values that belong only to the inheriting tree.

is there an obvious solution i'm missing? should i not use inheritance? should rewrite all the methods?

Thanks, John

A: 

It is difficult to answer your question without knowing the actual use-case you need the tree structure for, but in general I would take sides with the suggestions made in the comments:

  • Declare a class ComplexData containing your two ints and declare ComplexTree as a subclass of Tree<ComplexData>.

  • You could even declare ComplexData<TData> itself generic so it can contain an additional TData, and then declare ComplexTree<TData> as a subclass of Tree<ComplexData<TData>>.

  • You need to be clear on the code contract for the methods that run your algorithms — i.e. what is the method actually supposed to do, in general/abstract terms, not in terms of a particular use-case. If the contract is that it returns a collection of TData objects, then obviously that is what it should do, irrespective of whether you are running it on a simple tree or a subclass. If the contract is more abstract and the behaviour should depend on the subclass, then maybe it should be a virtual method (or use protected virtual methods) that the subclasses can override.

Timwi