我正在设计一些Java对象来表示图形和树。对于我的用例,我将同时使用这两种数据类型,但我也希望图形算法能够在我的树上工作。
import java.util.List;
public interface Node<T> {
T getValue();
List<? extends Node<T>> getNeighbors();
void addNodes(List<? extends Node<T>> nodes);
}
public interface TreeNode<T> extends Node<T> {
List<? extends TreeNode<T>> getChildren();
void addChildren(List<? extends TreeNode<T>> treeNodes);
@Override
default List<? extends Node<T>> getNeighbors() {
return getChildren();
}
@Override
default void addNodes(List<? extends Node<T>> nodes) {
if(nodes.getClass().isInstance(getChildren().getClass())) {
addChildren((List<? extends TreeNode<T>>) nodes);
} else {
throw new RuntimeException("Type error!");
}
}
}
我的问题是我如何在TreeNode接口的Node接口中处理addNodes方法。 addNodes方法必须位于Node界面中,因为我希望允许人们编写可将节点添加至图形的代码。但是,我也不希望人们将任意节点添加到树节点(例如,将图节点添加到树节点)。
为了防止这种情况,我在运行时检查节点的类型,如果类型不正确,则会引发异常。我只是想知道这是否是实现我想要的最佳方法,或者是否有更好的做法?
感谢您的帮助:)
答案 0 :(得分:2)
如果我的理解正确,那么您想要的是所谓的curiously recurring template pattern(有所变化)。 $ cat -n solution.sh
1 #!/bin/bash
2
3 grep -Po '\b(first|third|Any1):\w+' | cut -d: -f2
4
$ cat infile.txt
Something(first:test, second:test2, third:test4, fourth:test4, fifth(Field(test:1, test2:test2,...)), Any1:test1, Any2:test3.
$ solution.sh < infile.txt
test
test4
test1
类型不仅需要根据其有效负载类型(T)进行参数化,而且还需要根据其可以使用的节点类型进行参数化。所以你想要类似的东西:
Node
演示(仅显示编辑):https://ideone.com/44qrmX
答案 1 :(得分:0)
我的看法是Node
是一些数据的容器。 Tree
和Graph
是维护节点之间关系的两种方法。所以也许应该定义三个类:
import java.util.List;
public class Node<T> {
private T value;
public Node(T value) { this.value = value; }
T getValue() { return value; }
}
public abstract class Tree<T> {
private Node<T> root;
public abstract List<? extends Node<T>> getChildren();
public abstract void addChildren(List<? extends Node<T>> nodes);
public Tree(Node<T> root) { this.root = root; }
}
public abstract class Graph<T> {
private Node<T> root;
public abstract List<? extends Node<T>> getNeighbors();
public abstract void addNeighbors(List<? extends Node<T>> nodes);
public Graph(Node<T> root) { this.root = root; }
}
编辑:如果您希望使用共享遍历算法,可以将它们放在单独的类中,并让Tree和Graph使用类似的语义,如下所示:
// common semantics for node containers
public interface NodeContainer<T> {
List<? extends Node<T>> getRelatedNodes();
}
public abstract class Tree<T> implements NodeContainer<T> {
... // same as above
@Override
public List<? extends Node<T>> getRelatedNodes() {
return getChildren();
}
}
public class NodeContainerTraversal {
public void bfs (NodeContainer<?> container) {
...
}
}