Для чого застосовуються менш обмежувальні модифікатори доступу членів, ніж модифікатор доступу класу?


9

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

Конкретним прикладом може бути:

package apples;

class A { // package private
    public int foo() { // public (=> less restrictive than *package private*)
        return 42;
    }
}

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

  • Чи правильно моє розуміння?
    • Якщо ні, то які наслідки?
  • Які можуть бути поважні причини мати менш обмежувальні модифікатори доступу членів?
  • Нарешті, яких найкращих практик слід дотримуватися?

Я також робив деякі експерименти, тому що я думав, що це може мати наслідки, коли я починаю передавати посилання на функції, але навіть тоді модифікатор доступу не має значення.

Ситуація, яку я сконструював, така:

  • apples.Bнадає загальнодоступний метод, на bla()який повертається посилання на apples.A.foo.
  • Потім pizzas.Cдзвонить, apples.B.blaщоб отримати посилання на нього, A.fooі викликає його.
  • Таким чином, A.foo()це не безпосередньо видно C, а доступне лише опосередковано черезB.bla()

Я перевірив це, і це не має ніякого значення, роблю я модифікатор доступу foo() пакета приватним чи ні.

package apples;

import java.util.function.IntSupplier;

public class B {
    public IntSupplier getReferenceToAFoo() {
        A aInstance = new A();
        return aInstance::foo;
    }
}
package pizzas;

import apples.B;

import java.util.function.IntSupplier;

public class C {
    private int callAFooIndirectly() {
        B bInstance = new B();
        IntSupplier intsupplier = bInstance.getReferenceToAFoo();
        return intsupplier.getAsInt();
    }

    public static void main(String[] args) {
        C cInstance = new C();

        int i = cInstance.callAFooIndirectly();
        System.out.println(i);
        assert 42 == i;
    }
}

2
На сьогодні найпоширеніша причина такого дизайну - це реалізація публічних методів API (таких як інтерфейси або розширені абстрактні класи), використовуючи непублічні класи. Сам JDK рясніє такими класами (наприклад, java.util.Collections.SingletonSet<E>є privateв java.util.Collections).
ernest_k

Відповіді:


8

Чи правильно моє розуміння?

Так.

Які можуть бути поважні причини мати менш обмежувальні модифікатори доступу членів?

Дві причини:

  • Іноді ви реалізуєте інтерфейс; Методи інтерфейсу повинні бутиpublic
  • Це полегшує зміну загального доступу до вашого класу. Наприклад, якщо ви позначаєте всі методи, якими ви хотіли б бути відкритими public, навіть у приватному класі пакетів, то пізніше все, що вам потрібно зробити, щоб зробити клас загальнодоступним, - додати publicдо декларації класу.

Нарешті, яких найкращих практик слід дотримуватися?

Це питання думки, тому не дуже підходить для запитання чи відповіді щодо переповнення стека. Робіть те, що вам і / або вашій команді здається розумним, та / або робіть те, що підказує керівництво зі стилю вашої команди.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.