Jakie jest zastosowanie mniej restrykcyjnych modyfikatorów dostępu do członów niż modyfikatora dostępu do klasy?

9

Powiedzmy, że mam klasę z niektórymi członkami, a członkowie mają mniej restrykcyjny modyfikator dostępu niż sama klasa.

Konkretnym przykładem może być:

package apples;

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

W moim rozumieniu modyfikator dostępu do klasy, który jest bardziej restrykcyjny niż modyfikator dostępu do elementu , zastąpi mniej restrykcyjne modyfikatory dostępu do elementu . Tak więc mniej restrykcyjny modyfikator dostępu do elementu nie powinien mieć żadnego efektu.

  • Czy moje rozumowanie jest prawidłowe?
    • Jeśli nie, jakie są konsekwencje?
  • Jakie mogą być ważne powody, aby mieć mniej restrykcyjne modyfikatory dostępu do elementu?
  • Wreszcie, jakie są najlepsze praktyki, których należy przestrzegać?

Przeprowadziłem też pewne eksperymenty, ponieważ pomyślałem, że może to mieć konsekwencje, gdy zacznę przekazywać odniesienia do funkcji, jednak nawet wtedy modyfikator dostępu nie wydaje się mieć znaczenia.

Sytuacja, którą zbudowałem, jest następująca:

  • apples.Bzapewnia metodę publiczną, bla()która zwraca odwołanie do apples.A.foo.
  • Następnie pizzas.Cwywołuje, apples.B.blaaby uzyskać odwołanie A.fooi wywołuje je.
  • Nie A.foo()jest więc bezpośrednio widoczny C, ale jest tylko pośrednio dostępny przezB.bla()

Przetestowałem to i nie ma znaczenia, czy modyfikator dostępu foo() pakietu zostanie ustawiony jako prywatny, czy nie.

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;
    }
}

Stefan D.
źródło
2
Zdecydowanie najczęstszym powodem tego rodzaju projektowania jest zapewnienie implementacji publicznych metod API (takich jak interfejsy lub rozszerzone klasy abstrakcyjne) przy użyciu klas niepublicznych. Sam JDK jest pełen takich klas (np. java.util.Collections.SingletonSet<E>Jest privatew java.util.Collections).
ernest_k

Odpowiedzi:

8

Czy moje rozumowanie jest prawidłowe?

Tak.

Jakie mogą być ważne powody, aby mieć mniej restrykcyjne modyfikatory dostępu do elementu?

Dwa powody:

  • Czasami implementujesz interfejs; metody interfejsu muszą byćpublic
  • Ułatwia zmianę ogólnego dostępu do klasy. Na przykład, jeśli zaznaczysz wszystkie metody, które kiedykolwiek chciałbyś być publiczne public, nawet w klasie prywatnej pakietu, to później wszystko, co musisz zrobić, aby uczynić klasę publiczną, to dodać publicdo deklaracji klasy.

Wreszcie, jakie są najlepsze praktyki, których należy przestrzegać?

To kwestia opinii, więc nie pasuje do pytania lub odpowiedzi przepełnienia stosu. Rób to, co wydaje się rozsądne tobie i / lub zespołowi, i / lub rób to, co nakazuje ci przewodnik stylu twojego zespołu.

TJ Crowder
źródło