Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/oop/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
实现方法中运行时类型检查的Java问题_Java_Oop_Design Patterns - Fatal编程技术网

实现方法中运行时类型检查的Java问题

实现方法中运行时类型检查的Java问题,java,oop,design-patterns,Java,Oop,Design Patterns,我正在设计一些java对象来表示图形和树。对于我的用例,我将使用这两种数据类型,但我也希望我的图形算法在我的树上工作 import java.util.List; public interface Node<T> { T getValue(); List<? extends Node<T>> getNeighbors(); void addNodes(List<? extends Node<T>> nodes)

我正在设计一些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!");
        }
    }
}
import java.util.List;
公共接口节点{
T getValue();

列表在我看来,
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; }
}
import java.util.List;
公共类节点{
私人T值;
公共节点(T值){this.value=value;}
T getValue(){返回值;}
}
公共抽象类树{
私有节点根;

公共抽象列表如果我理解正确,您想要的是(一个变体)所谓的。
节点
类型不仅需要通过其有效负载类型(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);
    }
}
公共接口节点{
T getValue();
列出getneights();
void addNodes(列表节点);
}
公共接口树节点扩展节点{
列出getChildren();
void addChildren(列出树节点);
@凌驾
默认列表getNeights(){
返回getChildren();
}
@凌驾
默认的void addNodes(列表节点){
添加子节点(节点);
}
}

演示(仅显示编译):

我不理解代码中
节点
树节点
之间的区别。在我看来,
节点
是一些数据的容器。
是维护节点之间关系的两种方法。因此,也许应该定义三个类来表示这一点design@AdamSiemion节点是一个图节点,TreeNode是一棵树node@SharonBenAsher请您详细说明一下好吗?
nodes.getClass()
您现有的它永远不会工作,因为
getClass()
始终返回运行时类型,该类型将删除实际参数化类型。因此,无论节点的子类型如何,类都将进行相同的比较。如果要检查列表中值的类型,则需要为元素类型获取
对象,例如
;没有此类由于擦除,将其作为
类进行处理。这种方法的问题是:如果我为Graph类编写BFS,我就不能在tree类上使用它。那么tree和Graph之间的真正区别是什么?这只是语义吗?当有人使用TreeNode时,假设该节点满足tree属性。即树中没有圆。当有人使用一个常规节点,假设没有一种方法可以完成相同的事情而不需要人们指定N?不幸的是,没有。但是如果客户端代码直接与具体的子类型一起工作,比如
TreeNode
,那么就不需要显式地命名N的类型。是否可以编写代码它直接在这个节点接口上运行?我认为这是不可能的。我想要捕获的一个用例是为节点编写代码并在TreeNode中重用它,您只需要为N使用通配符类型。类似于
Node
的东西将允许您调用
getValue()
以类型安全的方式。您将无法向其中添加节点,但这是正确的,因为如果您只有一个
节点
,那么您就不知道要添加哪些节点作为其子节点。
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);
    }
}