Почему полиморфизм не работает, как я ожидал в моем коде? - PullRequest
2 голосов
/ 23 января 2012

Я довольно новичок в Java и столкнулся со странным поведением, которое я не могу объяснить, почему это происходит или где ошибка в моем коде.

Вот код:

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Iterator;

abstract class Shape {
    public abstract void printMe(String no);
}

final class Circle extends Shape {
    @Override
    public void printMe(String no){
        System.out.println("This is Circle no: " + no);
    }
}

final class Square extends Shape {
    @Override
    public void printMe(String no) {
        System.out.println("This is Square no: " + no);
    }
}

final class Triangle extends Shape {
    @Override
    public void printMe(String no) {
        System.out.println("This is Triangle no: " + no);
    }
}

public class Foo {
    private ArrayList<Shape> shapes;

    public Foo(){
        this.shapes   = new ArrayList<Shape>();

        this.shapes.add(new Circle());
        this.shapes.add(new Square());
        this.shapes.add(new Triangle());
    }

    public void printShapes(ArrayList<String> numbers){
        for(String s:numbers){
            Iterator<Shape> iter = this.shapes.iterator();
            Shape shape = iter.next();
            shape.printMe(s);
        }
    }

    public static void main(String[] args) {
        ArrayList<String> numbers = new ArrayList<String>(Arrays.asList("1", "2", "3"));
        Foo foo = new Foo();
        foo.printShapes(numbers);
    }
}

Вывод, который я ожидаю, будет:

This is Circle no: 1
This is Square no: 2
This is Triangle no: 3

Тем не менее, вывод, который я получаю:

This is Circle no: 1
This is Circle no: 2
This is Circle no: 3

Что я делаю не так?

Ответы [ 6 ]

3 голосов
/ 23 января 2012

Вытянуть эту строку из цикла:

 Iterator<Shape> iter = this.shapes.iterator();
1 голос
/ 23 января 2012

Посмотрите на Iterator<Shape> iter внутри вашего цикла.

  public void printShapes(ArrayList<String> numbers){
        for(String s:numbers){
            Iterator<Shape> iter = this.shapes.iterator();
            Shape shape = iter.next();
            shape.printMe(s);
        }
    }

Вы всегда захватываете первую фигуру (инициализируйте итератор, возьмите следующий)

1 голос
/ 23 января 2012

Вы всегда получаете новый итератор - вместо того, чтобы использовать тот же самый.

Мне непонятно, почему вы все равно делаете это; либо передайте целое число и цикл, пока он не закончится, или переберите фигуры и сохраните счетчик. Передача массива строк кажется мне неуклюжей.

public void printShapes() {
    int i = 1;
    for (Shape shape : shapes) {
        shape.printMe(i++); // And modify the method to take an int.
    }
}

Мне неудобно, когда фигура должна знать, что она может иметь позицию. Если это является обязательным требованием, создайте «PositionalShape» или что-то (но ew) или используйте формы для вывода строкового представления, которое может быть скомбинировано с дополнительной информацией, такой как позиция списка, или создать декоратор формы и т. Д.


// (If you're really trying to print the first n shapes)
public void printShapes(int n) {
    Iterator<Shape> iter = shapes.iterator();
    for (int i = 0; i < n; i++) {
        Shape shape = iter.next();
        shape.printMe("" + i+1);
    }
}
0 голосов
/ 23 января 2012

Вы всегда сбрасываете итератор:

Iterator<Shape> iter = this.shapes.iterator();
0 голосов
/ 23 января 2012

Следующие 2 строки должны быть в цикле: Shape shape = iter.next(); shape.printMe(s);

0 голосов
/ 23 января 2012

Я подозреваю, что вам нужно увидеть это в вашем отладчике, однако с

Iterator<Shape> iter = this.shapes.iterator();
Shape shape = iter.next();
shape.printMe(s);

Вы используете первый общий ресурс каждый раз (то есть круг)

Вы можете переместить iter объявление вне цикла, чтобы исправить это.

...