我正在为不同类型的树编写一组集合类。我这样做是作为一个学习练习,我也希望这是一些有用的东西。我真的很想用正确的方式来做这件事,所以我一直在阅读有效Java,我也一直在研究Joshua通过查看源代码实现集合类的方式。我似乎对正在做的事情有一个公平的想法,但我仍然有一些事情要解决。
我有一个Node<T>接口和一个实现Node接口的AbstractNode<T>类。然后我创建了一个GenericNode<T> (一个节点可以有0到n个子节点,它是n进制树的一部分),它扩展了AbstractNode<T>并实现了Node<T>。这部分很简单。
接下来,我创建了一个Tree<T>接口和一个实现Tree<T>接口的AbstractTree<T>类。之后,我开始编写GenericTree<T>类,扩展AbstractTree<T>并实现Tree<T>。这就是我开始有问题的地方。
就设计而言,GenericTree<T>只能由GenericTreeNode<T>类型的节点组成。这包括根。在我的Tree<T>接口中有:
public interface Tree<T> {
void setRoot(Node<T> root);
Node<T> getRoot();
List<Node<T>> postOrder();
... rest omitted ...
}而且,AbstractTree<T>实现了这个接口:
public abstract class AbstractTree<T> implements Tree<T> {
protected Node<T> root;
protected AbstractTree() {
}
protected AbstractTree(Node<T> root) {
this.root = root;
}
public void setRoot(Node<T> root) {
this.root = root;
}
public Node<T> getRoot() {
return this.root;
}
... rest omitted ...
}在GenericTree<T>中,我可以拥有:
public GenericTree(Node<T> root) {
super(root);
}但这意味着您可以使用Node<T>的任何子类型创建泛型树。还可以将树的根设置为Node<T>的任何子类型。我希望能够将节点的类型限制为它可以表示的树的类型。为了解决这个问题,我可以这样做:
public GenericTree(GenericNode<T> root) {
super(root);
}但是,setRoot仍然接受Node<T>类型的参数。这意味着用户仍然可以创建具有错误类型的根节点的树。如何执行此约束?我唯一能想到的办法是:
instanceof。我不是这个的超级粉丝。setRoot并让基类实现此方法。这意味着它不是契约的一部分,任何想要创建一种新型树的人都需要记住实现这个方法。有更好的办法吗?
第二个问题涉及postOrder的返回类型,即List<Node<T>>。这意味着,如果用户在GenericTree<T>对象上操作并调用postOrder,他或她将收到一个由Node<T>对象组成的列表。这意味着当迭代(使用foreach构造)时,如果希望使用仅在该类中定义的方法,则必须执行对GenericNode<T>的显式强制转换。我不喜欢把这个负担强加给用户。在这种情况下我有什么选择?我只能考虑从接口中删除该方法,并让子类实现此方法,同时确保它返回适当的Node<T>子类型的列表。但是,这再次将其从契约中删除,任何想要创建新类型树的人都必须记住实现此方法。有更好的办法吗?
发布于 2010-05-25 22:59:52
我觉得你把马车放在马前面。
实现Tree<T>和Node<T>的两个具体实例。只有在此之后,分析它们有哪些共同的实现,然后才实现您的Abstract类,如果它们在这一点上仍然有意义的话。
编辑
回答你的第二个问题:
如果简单的Node<T>没有在Tree接口中剪切它,那么您别无选择,只能将第二个参数声明为泛型接口,并在其上设置一个边界,如下所示
public interface Tree<
T,
TNode extends Node< T >
>
{
void setRoot(TNode root);
TNode getRoot();
List<TNode> postOrder();
... rest omitted ...
}然后是AbstractTree
public abstract class AbstractTree<
T,
TNode extends Node< T >
> implements Tree<T, TNode> {
protected TNode root;
protected AbstractTree(TNode root) {
this.root = root;
}
...
}然后是GenericTree
public class GenericTree< T >
extends AbstractTree< T, GenericNode< T > >
{
public GenericTree ( GenericNode< T > root )
{
super( root );
}
@Override
public List< GenericNode< T > > postOrder ( )
{
...
}
...
}https://stackoverflow.com/questions/2908952
复制相似问题