Управління доступом до класів у пакетах. Пакетний рівень доступу до класу. Загальнодоступний (public) рівень доступу до класу

Управління доступом до класів у пакетах. Пакетний рівень доступу до класу. Загальнодоступний (public) рівень доступу до класу


Зміст


1. Які причини в необхідності правильного управління доступом до вмісту бібліотек на мові Java? Для чого потрібно вміти правильно застосовувати засоби управління доступом?

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

2. Які існують рівні доступу до класів в цілому, що розміщуються в пакетах?

До класу, що є частиною пакету є два рівні доступу:

  • рівень доступу public. У цьому випадку клас є видимим з інших пакетів. Перед словом class ставиться модифікатор доступу public. Звертання до класу здійснюється з допомогою імені пакету та імені цього класу, розділених символом ‘ . ‘ (крапка);
  • пакетний рівень доступу. У цьому випадку перед словом class нічого не ставиться. В межах пакету класи з цього пакету є видимі один для одного.

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

3. Що означає термін “пакетний” рівень доступу (package access)?

Це є рівень доступу в межах пакету. Його ще називають доступ за замовчуванням. Такий рівень доступу вказується, якщо явно не задано специфікатору доступу (private, protected, public).

При пакетному рівні доступу член класу є доступний іншим класам поточного пакету. Для класів, які реалізовані в інших пакетах, даний член класу вважається прихованим або приватним (private).



4. Приклад, що демонструє “пакетний рівень доступу для двох класів

У прикладі оголошується проект з іменем DemoPackages. У проекті створено 2 пакети з іменами PackageA, PackageB. У пакеті PackageA реалізовано бібліотеку з 2-х класів, які мають імена ClassA1 (розміщується в модулі ClassA1.java) та ClassA2 (розміщується в модулі ClassA2.java). Початкова структура проекту зображена на рисунку 1.

Рис. 1. Фрагмент вікна Package Explorer. Структура пакету DemoPackages

Нижче наведено програмні коди модулів (файлів) ClassA1.java, ClassA2.java, ClassB1.java, ClassB2.java що відповідають класам ClassA1, ClassA2, ClassB1, ClassB2.

Текст модуля ClassA1.java. У класі коректно створюється об’єкт класу ClassA2. Це є логічно, оскільки класи ClassA1 та ClassA2 оголошені в одному пакеті і мають доступ в межах пакету.
Однак, спроба створити об’єкт класу ClassB1 з іншого пакету викличе помилку компіляції.

package PackageA;

class ClassA1 // немає явно заданого специфікатора public, доступ за замовчуванням
{
    int a1;

    public static void main(String[] args)
    {
        // доступ до класу ClassA2 з класу ClassA1 - коректно, класи в одному пакеті
        ClassA2 cA2 = new ClassA2();
        cA2.a2 = 109;

        // цей код не буде компілюватись: класи ClassA1 та ClassB1 в різних пакетах
        // PackageB.ClassB1 cB1 = new PackageB.ClassB1(); // помилка!
    }
}

Текст модуля ClassA2.java. У класі коректно створюється об’єкт класу ClassA1, тому що класи оголошуються в одному пакеті. Ну і звичайно, доступитись до класу ClassB1 за скороченим іменем не вийде, оскільки цей клас реалізований в іншому пакеті (PackageB).

package PackageA;

class ClassA2 // немає явно заданого специфікатора public, доступ за замовчуванням
{
    int a2;

    public static void main(String[] args)
    {
        // доступ з класу ClassA2 до класу ClassA1 - працює, обидва класи в одному пакеті
        ClassA1 cA1 = new ClassA1();
        cA1.a1 = 17;

        // PackageB.ClassB1 cB1 = new PackageB.ClassB1(); // а це помилка компіляції, класи в різних пакетах
    }
}

Текст модуля ClassB1.java. У модулі коректно створюється об’єкт класу ClassB2, тому що класи ClassB1, ClassB2 знаходяться в одному пакеті PackageB, доступ до яких здійснюється за замовчуванням. Спроба створити об’єкт класу ClassA1 є невдалою, оскільки клас ClassA1 оголошений в іншому пакеті і для нього не задано модифікатора доступу public.

package PackageB;

// немає явно заданого специфікатора public, доступ за замовчуванням (в межах пакету)
class ClassB1
{
    double b1 = 12.44; // внутрішня змінна

    public static void main(String[] args)
    {
        // доступ до класу ClassB2 з класу ClassB1
        ClassB2 cB2 = new ClassB2();
        cB2.b2 = 230;

        // тут виникне помилка компіляції:
        // PackageA.ClassA1 cA1 = new PackageA.ClassA1(); // помилка, ClassA1 оголошується в іншому пакеті
    }
}

Текст модуля ClassB2.java. У класі коректно ініціалізується змінна класу ClassB1 тому що класи ClassB1 та ClassB2 знаходяться в одному пакеті.

package PackageB;

// немає явно заданого специфікатора public, доступ за замовчуванням (в межах пакету)
class ClassB2
{
    int b2; // внутрішня змінна

    // ініціалізація працює, тому що класи в одному пакеті PackageB
    ClassB1 cB1 = new ClassB1();
}

5. Які переваги дає використання доступу в межах пакету (за замовчуванням)?

Доступ в межах пакету дає наступні переваги:

  • взаємозв’язані класи групуються в межах одного пакету. Ці класи легко взаємодіють один з одним;
  • немає надлишковості коду щоб доступитись до потрібних класів, що розміщуються в однакових пакетах. А, отже, код стає більш читабельним;
  • код пакету є повністю контрольований в межах пакету. Ніхто не зможе доступитись до класів за межами пакету, окрім Ваших власних класів, що реалізовані в пакеті.

6. Що означає тип доступу public для класу що реалізований у пакеті?

Клас в пакеті може бути загальнодоступним для використання в інших зовнішніх бібліотеках. У цьому випадку перед оголошенням класу вказується модифікатор доступу public:

package PackageName;

// ...

// оголошення загальнодоступного класу
public class ClassName
{
    // ...
}

Після такого оголошення можна звернутись до класу в пакеті з іншого пакету за допомогою виклику:

PackageName.ClassName

де PackageName – ім’я пакету, в якому реалізований public-клас з іменем PackageName.

У пакеті може бути оголошено не більше одного public-класу.

7. Приклад, що демонструє використання модифікатора public для класу в пакеті

Нехай у проекті з іменем DemoAccess створено два пакети з іменами PackageA та PackageB. У пакеті PackageA реалізовано клас ClassA, який має тип пакетний тип доступу (без модифікатора доступу). У пакеті PackageB реалізовано клас ClassB, який оголошено з модифікатором public.

Структура проекту DemoAccess детально зображена на рисунку 2.

Рис. 2. Структура проекту DemoAccess

Текст класу ClassA з пакету PackageA наступний.

package PackageA;

// клас оголошено як пакетний (без модифікатора public)
class ClassA
{
    public static void main(String[] args)
    {
        // Доступ до класу ClassB з пакету PackageB
        // працює, тому що клас PackageB.ClassB оголошено як public
        PackageB.ClassB cB = new PackageB.ClassB();

        cB.b = 40; // працює, тому що змінна b класу ClassB оголошена як public
    }
}

Як видно з вищенаведеного коду, можна без проблем доступитись до класу PackageB.ClassB, тому що цей клас оголошено з модифікатором доступу public.

Текст модуля ClassB.java, в якому реалізовано клас ClassB

package PackageB;

public class ClassB
{
    public int b = 20; // загальнодоступна змінна класу

    public static void main(String[] args)
    {
        // доступитись до класу PackageA.ClassA не можна, тому він оголошений як пакетний
        // PackageA.ClassA cA = new PackageA.ClassA(); - помилка компіляції
    }
}

Як видно з вищенаведеного коду, доступитись до класу PackageA.ClassA не вдасться, тому що цей клас оголошений як пакетий (без модифікатора доступу).

Важливо. Для того, щоб доступитись до внутрішньої змінної b класу ClassB з методів класу ClassA, ця змінна має бути оголошена з модифікатором доступу public.

8. Чи можна в оголошення імені класу додавати модифікатор доступу private?

Ні. Мова Java не підтримує використання модифікатора доступу private перед іменем класу. Тобто, наступний код є помилковим

// слово private заборонено
private class ClassName
{
    // ...
}

Це є логічно, оскільки для приховування класу в пакеті достатньо пакетного рівня доступу, який оголошується без всякого модифікатора

// пакетний рівень доступу до класу
class ClassName
{
    // ...
}

9. Чи можна в оголошення імені класу додавати модифікатор доступу protected?

Ні, не можна. Модифікатор доступу protected застосовується для класів, які надають свої члени даних та методи для породжених класів. У породжених класах protected-члени даних можна використовувати, однак їх не можна використовувати з об’єктів цих класів (ззовні). Але це вже зовсім інша тема.


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