The apply method above returns a LabeledTree. Now, I would like to create my own type of tree, say MyTree, which has the following structure.

class MyTree {
int value;
Label label;
public void myPrint();
}

Where do you suggest I should put this class in the inheritance tree so that I can directly instantiate objects of this class from the apply method? How do you think I should be going to design my system to maximize software re-use and not have to parse every tree to build objects of MyTree?

3 Answers
3

First of all, your tree definition exposes an important detail - each tree object is a node. This creates a whole bunch of conceptual units. In a real API, you would have a Tree interface, and an implementation that uses Nodes. All the data members would be in the node, except for the root node, which would be in your TreeImpl.

Second, I'm a big believer in naming being a critical first step for good and readable code, and that it often has an impact on the quality of your OO design.
A tree should not simply implement label. Can you say: "A tree is a label"?
On the other hand, if you had something like:
"TreeNode implements HasLabel", it would be clearer - "your tree node has a label".

Third, you are encountering the well known OOP problems of conformance and variance. With your current design, your root of the labeled tree has a label, but the lower nodes (which are simply Trees) do not have to be a labeled tree. This would be fun to debug. Generics can help you address this, but make sure to read Effective Java to understand how constraining generic types work.

I agree with @Uri that making Tree an Interface instead of an Abstract class would be an improvement.

If your parser doesn't know about subclasses of Tree, then one way is a reflection based scheme using Class.forName. Another way to deal with it would be to use a system where extension register when they are installed(A example here is the Eclipse plugin registry, although its a very complicated example of this pattern).

Your larger question is really about how to best organize parsers written in an OO language. There are many, many books on this subject. One that you might try looking at is this book:

There are pieces missing from your puzzle making a complete answer impossible from me, but as a first guess, I'd suggest genericizing your code as a first step towards generalizing it and allowing for easier extension.