Создать неизменный подкласс ArrayList - PullRequest
0 голосов
/ 05 мая 2018

Я занимаюсь разработкой простого подкласса класса ArrayList<Color>. В контексте моего приложения этот список действует как «список ссылок», возвращая Color объекты в следующем круговом и четко определенном порядке.

@SuppressWarnings("serial")
public final class ColorList extends ArrayList<Color> {

    private static int colorIndex = -1;

    public ColorList() {

        this.add(Color.CYAN);
        this.add(Color.DARK_GRAY);
        this.add(Color.GRAY);
        this.add(Color.GREEN);
        this.add(Color.BLUE);
        this.add(Color.LIGHT_GRAY);
        this.add(Color.MAGENTA);
        this.add(Color.ORANGE);
        this.add(Color.PINK);
        this.add(Color.RED);
        this.add(Color.YELLOW);
    }

    //if the color chosen is not the last one, increment index and get it.
    public Color getNextColor() {
        Color color = null;
        if(colorIndex != this.size() - 1) {
            color = this.get(++colorIndex);
        }
        else {
            colorIndex = -1;
            color = this.get(++colorIndex);
        }
        return color;
    }

По этой причине я хотел сделать этот класс неизменяемым, поскольку он предназначен для того, чтобы быть списком только для чтения, содержимое которого определяется при первом создании объекта и остается постоянным в течение всего времени его существования. В то же время мне нужно иметь возможность использовать getNextColor() для поддержания "круговой" моды.

Подходы приняты

  1. Вернуть неизменяемую ссылку.

    public static List<Color> getInstance(){
        return Collections.unmodifiableList(new ColorList());
    }
    

    Проблема с этим подходом состоит в том, что, возвращая ссылку List, не позволяет мне вызывать метод getNextColor(), что делает мой класс бесполезным. Приведение не решает проблему, потому что основной объект является экземпляр UnmodifiableRandomAccessList и не может быть приведен к ColorList.

  2. Методы переопределения, относящиеся к необязательным операциям

    @Override
    public boolean add(Color c) {
        throw new UnsupportedOperationException("color list is read-only");
    }
    <overridding other methods such as addAll, remove...>
    

    Как указано в документации , некоторые операции, помеченные как «необязательные», могут выполняться или не выполняться в зависимости от цели коллекции. Но это помешало бы мне добавлять цвета в первую очередь, как я это делаю в конструкторе, когда создается объект.

    Я думаю, что, возможно, я неправильно понимаю некоторые ключевые аспекты дизайна. Есть ли способ сделать мой класс неизменным, не ограничивая его (уже базовые) функциональные возможности?
    РЕДАКТИРОВАТЬ: требуется, чтобы этот класс явно расширял ArrayList по причине обратной совместимости. Следовательно, я не могу использовать класс-обертку, хотя я также думаю, что это будет самый правильный подход.

Ответы [ 2 ]

0 голосов
/ 05 мая 2018

Подумайте, в вашем случае лучше использовать композицию, а не наследование. В этом случае вы просто не предоставляете методы, которые могут изменить список цветов.

Вот пример кода

public final class ColorList {
    private final Color[] values;
    private int colorIndex;

    public ColorList(Color... colors) {
        this.values = colors;
    }

    public Color getNextColor() {
        if (colorIndex == values.length) colorIndex = 0;

        return values[colorIndex++];
    }

    public static void main(String[] args) {
        ColorList cl = new ColorList(Color.CYAN, Color.YELLOW, Color.WHITE);

        System.out.println(cl.getNextColor());
        System.out.println(cl.getNextColor());
        System.out.println(cl.getNextColor());
        System.out.println(cl.getNextColor());
    }
}

Есть несколько моментов, которые стоит упомянуть в предоставленном вами исходном коде:

  • Переменная colorIndex является статической, поэтому она используется всеми экземплярами класса ColorList. Если более одного экземпляра вызывают getNextColor (), результат будет противоречивым. Может быть, у вас есть идея создать класс Singleton, поэтому возможен только один его экземпляр?
  • список цветов в вашем коде всегда одинаков и известен во время компиляции, поэтому невозможно создать экземпляр ColorList с другим набором цветов. Это то, что должно быть?
0 голосов
/ 05 мая 2018

Если вы хотите, чтобы содержимое Списка было неизменным, тогда ваш конструктор работает, только вы должны вызывать super.add(...) вместо this.add(...); это будет означать, что ваши переопределения на add(...) будут разумны для защиты списка от внешнего вмешательства, позволяя при этом конструктору инициализировать объект для вас.

Ваш вопрос неясен, но если вы также хотите запретить прямой доступ к объектам в Списке, вы также можете явно переопределить get(...) и другие методы в зависимости от ситуации - хотя если вы это сделаете, то ваш метод getNextColor(...) должен вызвать super.get(...) вместо this.get(...).

Наконец, вам, вероятно, не нужна переменная-член colors, потому что вы расширяете список - нет смысла вкладывать в него другой список.

...