Подтвердить что ты не робот

Понимание ключевого слова 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, поскольку объект не имеет суперкласса.

  1. Так как невозможно иметь экземпляр AbstractClass, но только один из его конкретных подклассов, мне также представляется следующее:

Формы, использующие ключевое слово super, действительны только в экземпляре метод, инициализатор экземпляра или конструктор или в инициализаторе переменная экземпляра класса. Если они появляются где-то еще, ошибка времени компиляции.

  1. Не тот случай.

Это ошибка времени компиляции, если текущий класс не является внутренним классом самого класса T или T.

Конечно, я могу использовать AbstractClass.this.m(), но это не то, о чем я прошу.

4b9b3361

Ответ 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 означает, что методы разрешаются во время компиляции, тогда как динамическое связывание происходит во время выполнения при использовании метода, который может быть переопределен несколькими подклассами.