我正在设计一些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 接口(interface)中 Node 接口(interface)中的 addNodes 方法。 addNodes 方法必须位于 Node 接口(interface)中,因为我希望允许人们编写可以将节点添加到图中的代码。但是,我也不希望人们向树节点添加任意节点(例如向树节点添加图形节点)。
为了防止这种情况,我在运行时检查节点的类型,如果类型不正确则抛出异常。我只是想知道这是否是完成我想要的事情的最佳方式或者是否有更好的做法?
感谢您的帮助:)
最佳答案
如果我理解正确的话,你想要的是所谓的 curiously recurring template pattern (的变体) 。 Node
类型不仅需要通过其有效负载类型 (T) 进行参数化,还需要通过其可使用的节点类型进行参数化。所以你想要这样的东西:
public interface Node<T, N extends Node<T, N>> {
T getValue();
List<N> getNeighbors();
void addNodes(List<N> nodes);
}
public interface TreeNode<T> extends Node<T, TreeNode<T>> {
List<TreeNode<T>> getChildren();
void addChildren(List<TreeNode<T>> treeNodes);
@Override
default List<TreeNode<T>> getNeighbors() {
return getChildren();
}
@Override
default void addNodes(List<TreeNode<T>> nodes) {
addChildren(nodes);
}
}
演示(仅显示编译):https://ideone.com/44qrmX
关于Java关于实现方法中运行时类型检查的问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53797703/