Освой программирование играючи

Сайт Александра Климова

Шкодим

/* Моя кошка замечательно разбирается в программировании. Стоит мне объяснить проблему ей - и все становится ясно. */
John Robbins, Debugging Applications, Microsoft Press, 2000

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

Определение класса может размещаться внутри определения другого класса. Такие классы называются вложенными или внутренними. Область видимости вложенного класса ограничена областью видимости внешнего класса. Поэтому, если вы создадите класс B внутри класса A, то класс B не сможет существовать независимо от класса A.

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

Существуют два типа вложенных класса - статические и нестатические.

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

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

Применение статического внутреннего класса означает следующее:

  • для создания объекта статического внутреннего класса не нужен объект внешнего класса
  • из объекта вложенного класса нельзя обращаться к нестатическим членам внешнего класса

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

Статический класс объявляется ключевым словом static. При этом класс должен обращаться к нестатическим членам своего внешнего класса при помощи объекта, т.е. он не может обращаться напрямую на нестатические члены своего внешнего класса. На практике подобные классы используются редко.


// внешний класс
class outerClassName {
    
    private static class innerClassName {
        // тело вложенного класса
    }
}

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

Нестатические вложенные классы называют также внутренними классами (inner). Внутренний класс имеет доступ ко всем переменным и методам своего внешнего класса и может непосредственно ссылаться на них.

Внутренние классы создаются внутри окружающего класса:

// внешний класс
class Outer {
    int outer_x = 9;
    
    void test() {
        Inner inner = new Inner();
        inner.display();
    }
    
    // внутренний класс
    class Inner {
        void display() {
            Log.i(TAG, outer_x);
        }
    }
}

class MainActivity...{
    // В методе onCreate() активности
    Outer outer = new Outer();
    outer.test();
}

Внутренний класс Inner определён в области видимости класса Outer. Поэтому любой код в классе Inner может непосредственно обращаться к переменной outer_x. Когда мы создаём экземпляр класса Outer и вызываем метод test(), то создаём также экземпляр класса Inner с вызовом метода display().

Кстати говоря, внутренний класс можно определить не только на уровне класса, но и внутри метода или внутри тела цикла.

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

Объект внутреннего класса связан с внешним объектом-создателем и может обращаться к его членам без каких-либо дополнительных описаний. Для внутренних классов доступны все элементы внешнего класса.

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

Анонимные классы

Существует разновидность внутреннего класса, которая называется анонимным классом, так как у него нет имени. Подобные классы очень часто встречаются в примерах на Android. Например, когда вы пишете код для щелчка или других событий.


seekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
    @Override
    public void onProgressChanged(SeekBar seekBar, int i, boolean b) {
        
    }

    @Override
    public void onStartTrackingTouch(SeekBar seekBar) {

    }

    @Override
    public void onStopTrackingTouch(SeekBar seekBar) {

    }
});

В этом коде вы используете конструкцию new SeekBar.OnSeekBarChangeListener(), но обходитесь без создания переменной для этого класса.

Реклама