Вкладені класи та внутрішні класи. Статичні вкладені класи. Приклади

Вкладені класи та внутрішні класи. Статичні вкладені класи. Приклади


Зміст


1. Які класи називаються вкладеними класами? Особливості використання вкладених класів

Вкладений клас – це клас, який оголошений в іншому класі. При оголошенні вкладеного класу в межах іншого (у блоці фігурних дужок {}) цей вкладений клас сприймається як член охоплюючого його класу.

Вкладений клас має доступ до усіх членів даних та методів охоплюючого класу (навіть до private-членів даних), тому що він отримує посилання на зовнішній об’єкт (об’єкт охоплюючого класу) який його створив.

Клас може містити будь-яку кількість вкладених класів.

Наприклад

class OutClass {
    // члени даних та методи охоплюючого (зовнішнього) класу
    // ...

    class InClass {
        // члени даних та методи вкладеного (внутрішньогоі) класу
        // ...
    }
}

У вищенаведеному прикладі оголошується вкладений клас з іменем InClass в межах області дії охоплюючого класу з іменем OutClass.

 

2. Чи може вкладений клас існувати незалежно від класу, який його охоплює?

Вкладений клас не може існувати незалежно від охоплюючого класу. Однак, об’єкт вкладеного класу можна створювати.

 

3. Які існують типи вкладених класів з точки зору доступу до класу?

Існує два типи вкладених класів:

  • статичні вкладені класи. Такі класи оголошуються з модифікатором доступу static;
  • нестатичні вкладені класи або внутрішні класи. Це класи, які оголошуються в межах фігурних дужок зовнішнього (охоплюючого) класу.

 



4. Що означають терміни “внутрішній клас” та “вкладений клас”?

Внутрішній клас – це звичайний нестатичний вкладений клас. Тобто, це клас, який оголошений в межах іншого класу без ключового слова static. Якщо клас оголошений з ключовим словом static (статичний вкладений клас), то такий клас ще називають вкладеним класом.

 

5. Особливості оголошення та використання статичного вкладеного класу у нестатичному охоплюючому класі. Приклад

Якщо вкладений клас оголошено з ключовим словом static, то в цьому випадку можна виділити такі основні моменти:

  • будь-який public-статичний клас має глобальну область видимості, тобто він є видимим з усіх класів. А тому, можна звертатись до імені цього класу з врахуванням ієрархії вкладення. Наприклад, якщо статичний клас з іменем B є вкладений в клас з іменем A, то звертання до цього класу буде A.B;
  • зі статичного вкладеного класу не можна безпосередньо доступитись до нестатичних членів даних та методів охоплюючого класу. Однак, можна доступитись до статичних членів даних охоплюючого класу;
  • з охоплюючого класу не можна доступитись до нестатичних public-членів даних та методів статичного внутрішнього класу безпосередньо. Для забезпечення доступу має бути створений об’єкт статичного вкладеного класу.

Приклад.

Оголошується клас OutData, в якому оголошено вкладений статичний клас InData. Клас InData містить

// охоплюючий клас
class OutClass {
    int d;
    int x;

    // конструктор
    OutClass() {
        d = 15;
        x = 20;
    }

    // внутрішній метод класу OutClass
    void DemoOut() {       
        // можна оголошувати об'єкт вкладеного статичного класу
        InClass ic = new InClass();

        // доступ до внутрішніх даних статичного класу InClass через об'єкт класу
        ic.a = 25;
        ic.d = 33;

        // можна оголошувати об'єкт охоплюючого класу
        OutClass oc = new OutClass();
        oc.d = 78;
        oc.x = 323;      
    }

    // вкладений статичний клас
    static class InClass {
        int a;
        int d;

        // конструктор
        InClass() {
            // доступ до змінних a, d цього класу
            a = 5;
            d = 10;

            // неможна доступитись до змінних d,x класу OutClass,
            // тому що зі статичного класу до нестатичного члена даних немає доступу
            //x = 30; - помилка
        }    

        // внутрішній метод
        void DemoIn() {
            // можна створювати об'єкт класу OutClass
            OutClass oc = new OutClass();
            oc.d = 55;
            oc.x = 77;

            // можна створювати об'єкт статичного класу InClass
            InClass ic = new InClass();
            ic.a = 33;
            ic.d = 55;
        }
    }    

    void DemoMethod() {         
        // доступ до статичного класу з нестатичного методу
        OutClass.InClass IC = new OutClass.InClass();
        int t;           
        t = IC.a;
        System.out.println("t = " + t);         
    }
}

Нижче демонструється використання класів OutClass та InClass

// можна оголошувати об'єкти як охоплюючого так і внутрішнього класів
OutClass.InClass iC = new OutClass.InClass(); // створити екземпляр зі статичного класу
OutClass oC = new OutClass(); // створити екземпляр з охоплюючого нестатичного класу
int t;

t = iC.a; // t = 5
t = oC.d; // t = 15

// демонстрація виклику методів класів OutClass та OutClass.InClass
iC.DemoIn();
oC.DemoOut();

 

6. Особливості використання вкладених класів у випадку, коли обидва класи оголошені як нестатичні. Приклад

Охоплюючий та вкладений класи можуть бути оголошені без ключового слова static. У цьому випадку робота з класами має такі особливості:

  • якщо у деякому класі оголошується вкладений нестатичний клас, то цей клас ще називають “внутрішнім” класом;
  • з вкладеного (внутрішнього) класу є доступ до всіх членів даних та методів охоплюючого класу;
  • щоб використати вкладений клас, у методі охоплюючого класу має бути створений екземпляр (об’єкт) вкладеного класу.

Приклад.

class OutClass {
    int d;
    int x;

    // конструктор
    OutClass() {
        d = 15;
        x = 20;
    }

    // внутрішній метод класу OutClass
    void DemoOut() {
        // можна оголошувати об'єкт вкладеного класу з охоплюючого класу
        InClass ic = new InClass();
        ic.a = 25;
        ic.d = 33;

        // можна оголошувати об'єкт охоплюючого класу
        OutClass oc = new OutClass();
        oc.d = 78;
        oc.x = 323;

        // неможна безпосередньо доступитись до даних та методів вкладеного класу з охоплюючого,
        // тому що не створено екземпляру вкладеного класу
        // InClass.this.a = 22; - помилка!
    }

    // вкладений нестатичний клас
    class InClass {
        int a;
        int d;           

        // конструктор
        InClass() {
            // доступ до змінних a, d вкладеного класу InClass
            a = 5; // OutClass.InClass.this.a = 5
            OutClass.InClass.this.d = 10; // d = 10;

            // можна доступитись до змінних d,x класу OutClass
            x = 30;
            OutClass.this.d = 35;
        }    

        // внутрішній метод
        void DemoIn() {
            // можна створювати об'єкт класу OutClass
            OutClass oc = new OutClass();
            oc.d = 55;
            oc.x = 77;

            // можна створювати об'єкт класу InClass
            InClass ic = new InClass();
            ic.a = 33;
            ic.d = 55;
        }
    }
}

 

7. Особливості використання вкладених класів у випадку, коли обидва класи оголошені як статичні

Статичні класи мають глобальну область видимості з усіх інших класів та методів (статичних і нестатичних) якщо вони оголошені як public.

Особливості використання вкладених статичних класів:

  • можна оголошувати екземпляри public-статичних класів;
  • на рівні доступу пакету заборонено оголошувати статичний клас (див. рисунок 1-1);
  • статичний клас можна оголошувати як вкладений клас в іншому нестатичному класі як було продемонстровано в п. 7 даної теми (рисунок 1-2).

Java Eclipse оголошення класу пакет

Рис. 1. Оголошення статичного вкладеного класу: 1 – помилка заборонено оголошувати в межах пакету; 2 – дозволено оголошувати в межах класу

Статичний вкладений клас може бути оголошений у статичному охоплюючому класі. Однак, цей статичний охоплюючий клас має бути реалізований всередині нестатичного охоплюючого класу. У цьому випадку отримується два рівні вкладення.

Нижче наведено спрощений приклад оголошення статичного вкладеного класу в статичному охоплюючому класі.

// охоплюючий нестатичний клас
class OutClass {
    int d;

    // вкладений статичний клас
    static class InClass {
        int d;

        // вкладений статичний клас у статичному охоплюючому класі InClass
        static class InClass2 {
            int d2;
        }
    }
}

Як видно з вищенаведеного коду, оголошується клас OutClass, який є охоплюючим по відношенню до статичного класу InClass. В свою чергу, статичний клас InClass є охоплюючим по відношенню до статичного класу InClass2.

Використання об’єкту класу InClass2 може бути таким

// оголосити об'єкт класу OutClass.InClass.InClass2
OutClass.InClass.InClass2 obj = new OutClass.InClass.InClass2();
int t;

obj.d2 = 23; // OutClass.InClass.InClass2.d
t = obj.d2;

 

8. Особливості оголошення та використання нестатичного вкладеного класу у статичному охоплюючому класі

У статичному охоплюючому класі оголосити нестатичний вкладений клас можна. Однак, при спробі створити екземпляр такого нестатичного класу компілятор Java видасть помилку

No enclosing instance of type OutClass.InClass is accessible. Must qualify the allocation with an enclosing instance of type OutClass.InClass (e.g. x.new A() where x is an instance of OutClass.InClass).

Отже, використовувати нестатичні вкладені класи в статичних охоплюючих класах заборонено.

 


Зв’язані теми