Расширение неуниверсального класса на универсальный класс - PullRequest
2 голосов
/ 19 мая 2011

Java-класс CircularFifoBuffer в пакете org.apache.commons.collections.buffer не является универсальным и может хранить объекты любого класса.

Я хотел бы создать обобщенную версию этого, которая может содержать только объекты класса T. Моей первой мыслью было расширить CircularFifoBuffer и просто написать новый метод 'add':

public class CircularFifoQueue<T> extends CircularFifoBuffer {

    public boolean add(T data) {
        return super.add(data);
    }    

}

Однако это оставляет старый метод add на месте, позволяя добавлять объекты произвольного класса. Есть ли способ обойти это, используя наследование, а не композицию (чтобы мне не пришлось повторно реализовывать все методы CircularFifoBuffer), но не позволяет пользователям класса добавлять не-T объекты?

Ответы [ 4 ]

3 голосов
/ 19 мая 2011

Одна идея состоит в том, чтобы реализовать свой собственный буфер, который просто оборачивает исходный:

public class CircularFifoQueue<T> { 
  private CircularFifoBuffer buffer = new CircularFifoBuffer();

  public boolean add(T data) {
     return buffer.add(data);
  }    

  // implement all other methods that are needed
}

Таким образом, внутренний буфер забирает все, но оболочка гарантирует, что могут быть добавлены только объекты типа T.Проблема: сейчас буфер не реализует интерфейс.Так что его использование сейчас немного ограничено (вы не можете использовать его, например, если вам нужно отправить Buffer)

3 голосов
/ 19 мая 2011

Нет, вы не можете.

Простая причина, почему это невозможно, - полиморфизм.Если бы вы могли удалить метод add(Object), вы бы нарушили полиморфизм для класса CircularFifoBuffer.

Вот простой пример.Чтобы это работало правильно, ваш класс CircularFifoQueue должен иметь метод add(Object).

CircularFifoBuffer buffer = new CircularFifoQueue<String>();
buffer.add(new Object());
0 голосов
/ 19 мая 2011

Вы можете попробовать следующий подход.Это не очень элегантно, но оно должно выполнять свою работу:

public class CircularFifoQueue<T> extends CircularFifoBuffer {
    private Class<T> klass;
    public CircularFifoQueue(Class<T> klass) {
        this.klass = klass;           
    }

    @Override
    public boolean add(Object data) {
        T typedData = klass.cast(data);
        return super.add(typedData);
    }

    public boolean add(T data) {
        return super.add(data);
    }            
}
...
CircularFifoQueue<String> queue = new CircularFifoQueue<String>(String.class);
queue.add("hello"); // should work
queue.add(123L); // should throw ClassCastException

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

0 голосов
/ 19 мая 2011

@ Ответ Вивьен уже объясняет, почему на самом деле не имеет смысла делать это (дополнительную информацию читайте о принципе подстановки Лискова ).

Однако вы можете обойти это, определив пользовательское переопределение add(Object), которое просто генерирует исключение во время выполнения.Это не очень элегантное решение, но если вам нужно быстрое решение, то это может быть именно так.

...