Переопределение списка и практика Java

У меня есть три класса (число, вероятно, возрастет в будущем):

public inteface Base{ }

public class Select implements Base{ }

public class Ast implements Base{ }

public class Gt implements Base{ }

Мне также нужен класс List

BaseList extends ArrayList<Base>{
    public boolean add(Base b){
        throw new UnsupportedOperationException("You should use add%ConcereteBaseType% method instead");
    }

    public boolean add(Select s){ }

    public boolean add(Ast a){ }

    public boolean add(Gt g){ }
}

Причина, по которой я делал это, был тот факт, что я не хочу, чтобы кто-то добавлял элементы через указатель на Base. В моей конкретной ситуации это было бы небезопасно.

Но недостатком является то, что он будет обнаружен только во время выполнения.

Мне также нужно перебирать список.

Хорошо ли это делать?

Ответ 1

Использование interface в порядке. (Включение Base в абстрактный класс не купит вам ничего здесь.)

Здесь вы должны отдать предпочтение композиции над наследованием и реализовать Iterable<Base>, чтобы иметь возможность использовать ее в расширенных для циклов и т.д.

class BaseList implements Iterable<Base> {
    private List<Base> list = new ArrayList<>();

    public boolean add(Select s) {
        return list.add(s);
    }

    public boolean add(Ast a) {
        return list.add(a);
    }

    public boolean add(Gt gt) {
        return list.add(gt);
    }

    @Override
    public Iterator<Base> iterator() {
        return Collections.unmodifiableList(list).iterator();
    }
}

Затем вы можете перебирать список следующим образом:

for (Base b : yourBaseList) {
    ...
}

Ответ 2

Вы можете сделать класс Base a abstract, поскольку они никогда не могут быть созданы, ваш список будет безопасным.

Мой путь: я действительно не понимаю, почему вы хотели бы генерировать исключение для add(Base b), когда base является interface, который сам по себе никогда не может быть объектом.

В противном случае используйте шаблон delegate/wrapper, значит: не расширяйте ArrayList, а создайте класс, содержащий ArrayList.

class BaseList {
    private List<Base> list = new ArrayList<>();

    public boolean add(Select s) {
         return list.add(s);
    }
    //etc
}