toString() 方法中没有发生递归

Recursion not occurring in toString()-method

我正在创建一个包含 Bags 和 Items 的复合模式,其中 Bags 可以包含 Items 但 Items它不能包含任何东西。

当我在根上使用 toString() 方法时,我希望 Bag 中的每个 Entity 都打印在 "natural language" 中。目前看来 toString() 方法中的递归被破坏了,我不确定为什么。我尝试在 while 循环之前使用 System.out.println(1);,但它只打印了一次,这就是我认为递归被破坏的原因。

Item-class;

public class Item extends Entity {

public Item(String theName) {
    this.name = theName;
}

public String toString() {
    String output = String.format("a %s", name);
    return output;
}
}

Bag-class

import java.util.*;

public class Bag extends Entity {
private List<Entity> children = new ArrayList<Entity>();

public Bag(String theName) {
    this.name = theName;
}

public void add(Entity entity) {
    children.add(entity);
}

public String toString() {
    String output = String.format("a %s", name);
    Iterator<Entity> itemIterator = children.iterator();
    output += " containing ";

    Entity current = itemIterator.next();
    while (itemIterator.hasNext()) {
        output += current.toString();

        Entity next = itemIterator.next();
        if (next instanceof Item) {
            output += ", ";
        } else if (next instanceof Bag) {
            output += " and ";
        }
        current = next;
    }
    return output;
}
}

Entity-class;

public abstract class Entity {

protected String name;
protected int weight;

public abstract String toString();
public abstract int getWeight();

}

MyFrame 包含 main-方法;

public class MyFrame {

public static void main(String[] args) {
    Bag sack = new Bag("sack");
    Bag pouch = new Bag("pouch");
    Bag suitcase = new Bag("suitcase");

    Item perfume = new Item("perfume");
    Item deodorant = new Item("deodorant");
    Item toothbrush = new Item("toothbrush");

    Item hairtie = new Item("hairtie");
    Item pen = new Item("pen");
    Item sock = new Item("sock");

    Item shirt = new Item("white shirt");
    Item shirt2 = new Item("black shirt");

    pouch.add(toothbrush);
    pouch.add(perfume);
    pouch.add(deodorant);

    sack.add(pen);
    sack.add(hairtie);
    sack.add(sock);
    sack.add(pouch);

    suitcase.add(shirt);
    suitcase.add(shirt2);
    suitcase.add(sack);

    System.out.println(suitcase.toString());

}
}

我要的文字是; "a suitcase containing a white shirt, a black shirt and a sack containing a pen, a hairtie, a sock and a pouch containing a toothbrush, a perfume, a deodorant"

我得到的文字是; "a suitcase containing a white shirt, a black shirt and"

你在 while 条件下出错

if (!itemIterator.hasNext()) return output;
Entity current = itemIterator.next();

while (true) {
    output += current.toString();

    if (!itemIterator.hasNext()) break;

    Entity next = itemIterator.next();
    // ......
    current = next;
}
return output;

你基本上跳过了最后一个实体

改变

return output;

return output + current;

您没有将最后一个元素附加到输出中。

此外,你在检查Iterator::hasNext之前调用Iterator::next,如果你有一个空的Bag,就会有一个NoSuchElementException

迭代器的使用在其他答案中已经被批评了;还应注意边界条件:0 或 1 children.

public String toString() {
    String output = String.format("a %s", name);
    if (!children.isEmpty()) {
        // Unfortunately because of the recursion the following
        // cannot be done.
        //String list = children.stream()
        //    .map(Entity::toString).collect(Collectors.join(", "));
        //output += list.replaceFirst(", ([^,]*)$", " and ");

        // Iterating from the back reversed, allows an easy
        // discrimination of comma and "and."
        StringBuilder list = new StringBuilder();
        String separator = " and ";
        ListIterator<Entity> itemIterator = children.listIterator(children.size());
        while (itemIterator.hasPrevious()) {
            Entity entity = itemIterator.previous();
            list.insert(0, entity.toString());
            if (itemIterator.hasPrevious()) {
                list.insert(0, separator);
                separator = ", ";
            }
        }
        output += list.toString();
    }
    return output;
}