У меня есть несколько классов Java, которые расширяют различные реализации универсального интерфейса List. Они просто регистрируют все, что добавляется в список.
Список LoggingArrayList показан ниже. Как следует из названия, он расширяет ArrayList. Класс LoggingLinkedList идентичен классу, за исключением того, что он расширяет LinkedList.
Моя главная цель — избежать дублирования всего общего кода только для того, чтобы я мог использовать другой базовый класс. Я стараюсь максимально придерживаться принципа DRY (не повторяйся).
Прежде всего, пожалуйста, не предлагайте лучший способ регистрации. Это совсем не мое настоящее приложение. Это просто простой способ продемонстрировать проблему, с которой я столкнулся.
У меня два тесно связанных вопроса. Первый вопрос в заголовке. Как я могу сослаться на «супер» метод в классе Java, который реализует интерфейс, но не расширяет другой класс?
Класс LoggingArrayList, как показано ниже, работает нормально, но когда я изменяю объявление класса с ...extends ArrayList на ...implements List, тогда три ссылки на super.method() больше не вызываются, отсюда и мой первый вопрос.
Хороший ответ на мой второй вопрос почти сделает первый вопрос спорным. Второй вопрос заключается в следующем: есть ли способ объявить абстрактный базовый класс или, возможно, интерфейс, который расширяет List с реализациями по умолчанию различных методов add(), чтобы я мог просто расширить этот абстрактный базовый класс или реализовать этот интерфейс и указать только какой список будет основой для конкретного класса?
Например, я хотел бы сделать что-то вроде этого:
interface LoggingList<T extends Object, L extends List<T>> extends L
{
// overloaded methods go here as shown below
// with overloaded methods declared as default for the interface
}
... тогда я мог бы просто реализовать LoggingList один раз для каждой конкретной реализации List, не дублируя весь общий код. Тогда конкретные классы могут выглядеть примерно так, без дополнительного кода внутри их фигурных скобок:
public class LoggingArrayList<T extends Object> implements LoggingList<T, ArrayList<T>> {}
public class LoggingLinkedList<T extends Object> implements LoggingList<T, LinkedList<T>> {}
Проблема в том, что определение интерфейса, как я предложил, недопустимо (не будет компилироваться), а также ссылки на super.method(s) в коде, показанном ниже, недоступны, если я не сделаю LoggingList абстрактным подклассом вместо интерфейса а потом я снова оказываюсь там, где я сейчас.
Заранее спасибо за любые идеи о том, как выполнить мою СУХУЮ цель.
Вот весь мой класс LoggingArrayList.
public abstract class LoggingArrayList<T extends Object>
extends ArrayList<T>
{
protected void log(T e)
{
System.out.println(e == null ? "null" : e.toString());
}
@Override
public boolean add(T e) {
log(e);
// How do I reference a super.method()
// in a class that implements an interface
// but does not extend another class?
return super.add(e);
}
@Override
public boolean addAll(Collection<? extends T> clctn) {
boolean anyChanges = false;
for(T e : clctn)
{
// ensure that we call our overridden version of add()
// so it gets logged.
anyChanges = anyChanges || add(e);
}
return anyChanges;
}
@Override
public boolean addAll(int i, Collection<? extends T> clctn) {
for(T e : clctn)
{
// ensure that we call our overridden version of add()
// so it gets logged.
add(i, e);
i++; // keep the inserted elements in their original order
}
return !clctn.isEmpty();
}
@Override
public T set(int i, T e) {
log(e);
// How do I reference a super.method()
// in a class that implements an interface
// but does not extend another class?
return super.set(i, e);
}
@Override
public void add(int i, T e) {
log(e);
// How do I reference a super.method()
// in a class that implements an interface
// but does not extend another class?
super.add(i, e);
}
}