24/02/2024

Глава 10. Внутренние классы

Глава 10. Внутренние классы

Внутренние классы

Класс, размещенный в определении другого класса называется внутренним(inner class).

Как правило внешний класс содержит ссылку на внутренний класс.

Если нужно создать объект внутреннего класса где-нибудь за пределами внешнего класса или в статическом методе, нужно будет указать тип этого объекта следующим образом: ИмяВнешнегоКласса.ИмяВнутреннегоКласса.

Внутренний класс может обращаться к членам внешнего класса и ему доступны все элементы внешнего класса.

Внутренний класс хранит ссылку на внешний класс, поэтому существование внутреннего класса невозможно без внешнего если он не является статическим.

Если нужно получить ссылку на внешний класс то указывается имя класс и .this.

Если нужно создать объект внутреннего класса из внешнего, например в статическом методе или за пределом внешнего класса то используется объект внешнего класса и .new

Закрытый внутренний класс позволяет разработчику класса полностью запретить использование определенных типов и скрыть детали реализации класса.

Внутренние классы могут создаваться в методах и даже произвольных областях действия. Для этого есть 2 причины: 1. Нужно создавать и возвращать ссылки на некоторый интерфейс 2. Нужно решить сложную задачу и нужно создать класс, который будет задействован в его решении, но при этом сделать его недоступным для посторонних.

Внутренний класс может быть:

  1. Класс, определенный в методе - локальный внутренний класс. К нему невозможно обратиться за пределами метода, в котором он определяется;
  2. Класс, определенный в области действия внутри метода - например вложен в область действия команды if. Внутренний класс не доступен за пределами действия в которой он определяется;
  3. Анонимный класс, реализованный в интерфейсе; Если вы определяете анонимный внутренний класс и хотите использовать внутри него объект передаваемый в аргументе, то необходимо чтобы аргумент был обозначен как final иначе компилятор выдаст ошибку.
  4. Анонимный класс, расширяющий класс с конструктором, который не является конструктором по умолчанию. В название класса передаются нужные аргументы и задается определение класса;
  5. Анонимный класс, выполняющий инициализацию поля;
  6. Анонимный класс, выполняющий конструирование с использованием инициализации экземпляра (анонимные внутренние классы не могут иметь конструкторов)

В отличие от обычного класса анонимные внутренние классы могут либо расширять класс, либо реализовать интерфейс но не оба действия сразу.

Паттерн «Фабричный метод»

Вложенные классы

Если связь между объектом внутреннего класса и объектом внешнего класса не нужна, внутренний класс можно сделать статическим (объявить его как static). Такой класс называют вложенным.

Вложенный класс: 1. Для создания его объекта не нужен объект внешнего класса 2. Нельзя обращаться к членам не-статического объекта внешнего класса из объекта вложенного класса.

Статические поля и методы внутреннего класса определяются только на уровне внешнего класса. Вложенные классы таких ограничений не имеют. Уточнить!!!

Вложенный класс может быть частью интерфейса. Даже без специальных обозначений любой класс помещенный в интерфейс считается public и static. Это может быть удобно при здании общего кода, который должен использоваться со всеми реализациями интерфейса.

Неважно насколько глубоко вложен класс он будет иметь доступ ко всем полям и методам всех внешних классов.

Причина для использования внутренних классов: Каждый внутренний класс способен наследовать определенную реализацию. Таким образом внутренний класс не ограничен при наследовано в ситуациях, где внешний класс уже наследует реализацию.

Таким образом, внутренний класс выступает как «довесок» множественного наследования.

Для наследованная от внутреннего класса должна быть ссылка на внешний класс поэтому используется следующий синтаксис: extends ИмяВнешнегоКласса.ИмяВнутреннего класса и в конструктор нужно передать ссылку на внешний класс и определить его как СсылкаНаВнешнийКласс.super();

Переопределение внутреннего класса не имеет никакого эффекта. Внутренние класс совершенно отдельные составляющие, с независимым пространством имен, но можно явно унаследовать от внутреннего класса.

Локальный внутренний класс не имеет модификатора доступа, но имеет доступ к членам внешнего класса и final переменным. У локального внутренний класса может быть свой конструктор.

Анонимный внутренний класс не может содержать конструктора только инициализатор экземпляра.

Единственный довод в пользу локального внутреннего класс перед анонимным внутренним классом есть необходимость в именованном конструкторе и/или перегруженных конструкторах и возможность создавать более чем один объект такого класса.

#философия_java