试图通过在子类中扩展它来向类添加方法?

时间:2017-10-17 21:45:54

标签: java inheritance polymorphism

(TL; DR:跳到粗体。)

我正在尝试构建一个改进的Hydra的计算机模拟 - 在这个版本中,每个Hydra头可以有更多的Hydra头从它出来。我认为这是非常类似节点的,所以我首先构建了一个通用的Node类。每个Node对象都有一个ArrayList<Node> children,每个{(1}}也可以拥有自己的Node

虽然Hydra头部的结构与children相同,但行为却不同。 (例如。Node应该能够简单地移除它的孩子,而从Hydra移除头部也需要重新生成一些头部。)所以我构建了Node并添加了HydraNode extends Node等方法(删除头部(节点)但随后添加克隆)。 cutHead()是&#34; body&#34;并且Hydra为头。

问题是,因为所有子节点都存储为HydraNode,我可以

ArrayList<Node>

,但它的每个子节点实际上都是节点。这导致Hydra hydra = new Hydra(1,1,1) // Makes a Hydra with 3 levels (1 head, which has 1 head, which has 1 head). Node nodeAtLevel1 = hydra.getChildren.get(0); // Has to be declared as Node, not HydraNode, because getChildren() is a Node method, and returns an ArrayList<Node> of children. 中出现问题,我尝试运行main(),但不能,因为nodeAtLevel1.cutHead()cutHead()方法。

在对象包含自身的情况下,如何向类中添加功能?将对象扩展为HydraNode似乎不起作用,因为检索包含的对象将返回subclass类型的对象,而不是superclass。而我无法向下投掷它。我该怎么办?

Node.java

subclass

HydraNode.java(头脑)

public class Node {
    // Member variables
    private ArrayList<Node> children = new ArrayList<>(); // Holds "children" nodes.
    private int hierarchyLevel; // Where in the hierarchy is it?
    private int childCount = 0; //How many "child" nodes does this node have?

    // Constructors
    public Node(int hierarchyLevel) {this.hierarchyLevel = hierarchyLevel}
    public Node(int hierarchyLevel, int... nodesPerLevel) {this(hierarchyLevel;} //Adds children to this node, eg. {1,2,1} adds 1 child node at lvl 1, 2 children at lvl 2, each with 1 child of their own at level 3.

    // Methods
    public ArrayList<Node> getChildren() {return children;}
    public void addChild() {} // Adds a child directly to this node
    public void removeChild(int i) {}

    public Node getCopy() {} //Returns a clone of this Node and all its child nodes.

    public String toString() {} // Eg. Node at Level ___ has ____ children.

}

Hydra.java

public class HydraNode extends Node {
    // Constructors
    public HydraNode(int hierarchyLevel) { // Just call super, bc this is essentially a Node structure that just acts a little differently.
        super(hierarchyLevel);
    }
    public HydraNode(int hierarchyLevel, int... nodesPerLevel) {
        super(hierarchyLevel, nodesPerLevel);

    // Methods
    public void cutHead() {} // Cutting a Level 1 head, which is attached to the body (level 0), does not regrow. However, any other cut will multiply that branch's parent x3.
}

4 个答案:

答案 0 :(得分:3)

我们所做的演员建议都失败了,因为:

public HydraNode(int hierarchyLevel, int... nodesPerLevel) {
    super(hierarchyLevel, nodesPerLevel);

当您从Hydra构建HydraNodes时,您正在调用super()构造函数来链接它。这意味着您最终得到:

HydraNode -> Node -> Node

你应该打电话:

    this(hierarchyLevel, nodesPerLevel);

因此,创建链总会产生更多的HydraNodes。

HydraNode -> HydraNode -> HydraNode

然后,您将能够从节点转换 - &gt; HydraNode并按照许多回复中的说明调用cutHead

答案 1 :(得分:2)

您可以将超类投射到其子类,这称为向下转换

所以:

Node nodeAtLevel1 = hydra.getChildren.get(0);

你可以把它像:

HydraNode nodeAtLevel1 = (HydraNode) hydra.getChildren.get(0);

您还可以添加支票:

if (hydra.getChildren.get(0) instanceof HydraNode ) {
   HydraNode nodeAtLevel1 = (HydraNode) hydra.getChildren.get(0);
}

并不总是允许向下转发。您可以看到更多信息here

答案 2 :(得分:2)

为什么不将泛型用于子节点,如下所示:

public class Node<T extends Node<T>> {
        // Member variables
        private ArrayList<T> children = new ArrayList<>(); // Holds "children" nodes.
        private int hierarchyLevel; // Where in the hierarchy is it?
        private int childCount = 0; //How many "child" nodes does this node have?

        // Constructors
        public Node(int hierarchyLevel) {}
        public Node(int hierarchyLevel, int... nodesPerLevel) {} //Adds children to this node, eg. {1,2,1} adds 1 child node at lvl 1, 2 children at lvl 2, each with 1 child of their own at level 3.

        // Methods
        public ArrayList<T> getChildren() {return children;}
        public void addChild() {} // Adds a child directly to this node
        public void removeChild(int i) {}

        public T getCopy() {return null;} //Returns a clone of this Node and all its child nodes.

        public String toString() {return null;} // Eg. Node at Level ___ has ____ children.

    }

    public class HydraNode extends Node<HydraNode> {
        // Constructors
        public HydraNode(int hierarchyLevel) { // Just call super, bc this is essentially a Node structure that just acts a little differently.
            super(hierarchyLevel);
        }
        public HydraNode(int hierarchyLevel, int... nodesPerLevel) {
            super(hierarchyLevel, nodesPerLevel);
        }

        // Methods
        public void cutHead() {} // Cutting a Level 1 head, which is attached to the body (level 0), does not regrow. However, any other cut will multiply that branch's parent x3.
    }

        public class Hydra {


            // MAIN method
            public static void main(String[] args) {
                Hydra hydra = new Hydra(1,1,1);
                HydraNode head2 = hydra.body.getChildren().get(0).getChildren().get(0);
                System.out.println(head2.toString()); // >> Node at Level 2 has 1 child node.
                head2.cutHead(); //works now
            }

            // Member Variables
            public static int regrowFactor = 2; // Every time a head is cut off, the hydra clones the remaining branches. In the original video, the hydra forms two new clones.
            HydraNode body;

            // Constructors
            public Hydra() {
                body = new HydraNode(0); // the body is just a new Node at level 0
            }
            public Hydra(int... headsPerLevel) {
                body = new HydraNode(0, headsPerLevel);
            }
        }        

答案 3 :(得分:1)

为什么要使用这种继承?

使用单个HydraNode类,将Node的所有功能复制粘贴到其中,问题就解决了。