Понимание ключевого слова super для абстрактных классов
Рассмотрим следующий класс:
public abstract class AbstractClass {
public abstract String m();
public AbstractClass get(){
return new AbstractClass() {
@Override
public String m() {
return "Anonymous " + super.m(); //1, Compile-time erro
}
};
}
}
Непонятно, почему такое использование super
запрещено. В //1
происходит следующая ошибка:
Cannot directly invoke the abstract method m() for the type AbstractClass
Итак, я посоветовался с JLS 15.11.2 и не нашел ограничения, запрещающего компиляцию такого кода. Вот они:
Это ошибка времени компиляции, если формы с использованием ключевого слова super отображаются в объявлении класса Object, поскольку объект не имеет суперкласса.
- Так как невозможно иметь экземпляр
AbstractClass
, но только один из его конкретных подклассов, мне также представляется следующее:
Формы, использующие ключевое слово super, действительны только в экземпляре метод, инициализатор экземпляра или конструктор или в инициализаторе переменная экземпляра класса. Если они появляются где-то еще, ошибка времени компиляции.
- Не тот случай.
Это ошибка времени компиляции, если текущий класс не является внутренним классом самого класса T или T.
Конечно, я могу использовать AbstractClass.this.m()
, но это не то, о чем я прошу.
Ответы
Ответ 1
Ключевое слово super здесь не работает, потому что AbstractClass.m()
был объявлен абстрактным, и поэтому нет подходящей реализации его для родителя внутреннего класса. Помните, что внутренние классы не расширяют внешний класс (даже если он имеет тот же тип), они включают в себя ссылку на него.
Однако при работе с вызовом внутреннего класса во внешний класс (который, как я полагаю, вы хотели сделать здесь), используйте следующий синтаксис AbstractClass.this.m()
.
Следующее будет компилироваться и работать по назначению.
public abstract class AbstractClass {
public abstract String m();
public AbstractClass get(){
return new AbstractClass() {
@Override
public String m() {
return "Anonymous " + AbstractClass.this.m();
}
};
}
}
Ответ 2
Насколько я знаю, компилятор пытается использовать статическую привязку при использовании super.m();
. Поскольку метод super.m();
отсутствует, поскольку он абстрактный, компилятор уже жалуется во время компиляции.
Статическое связывание в Java означает, что методы разрешаются во время компиляции, тогда как динамическое связывание происходит во время выполнения при использовании метода, который может быть переопределен несколькими подклассами.