Qual é o uso de modificadores de acesso a membros menos restritivos que o modificador de acesso à classe?

9

Digamos que eu tenha uma classe com alguns membros e os membros tenham um modificador de acesso menos restritivo do que a própria classe.

Um exemplo concreto pode ser:

package apples;

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

Para meu entendimento, um modificador de acesso à classe que é mais restritivo do que o modificador de acesso ao membro , substituirá os modificadores de acesso ao membro menos restritivos . Portanto, um modificador de acesso a membros menos restritivo não deve ter efeito algum.

  • Meu entendimento está correto?
    • Se não, quais são as consequências?
  • Quais seriam os motivos válidos para ter modificadores de acesso a membros menos restritivos?
  • Finalmente, quais são as melhores práticas a seguir?

Também fiz algumas experiências porque achei que poderia ter consequências assim que começar a passar referências de funções, mas mesmo assim o modificador de acesso não parece importar.

A situação que eu construí é a seguinte:

  • apples.Bfornece um método público bla()que retorna uma referência a apples.A.foo.
  • Em seguida, pizzas.Cchama apples.B.blapara obter uma referência A.fooe chama.
  • Portanto, A.foo()não é diretamente visível C, mas é indiretamente acessível viaB.bla()

Eu testei e não faz diferença se eu faço o modificador de acesso do foo() pacote privado ou não.

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.
fonte
2
O motivo mais comum de longe para esse tipo de design é fornecer implementações de métodos públicos de API (como os de interfaces ou classes abstratas estendidas) usando classes não públicas. O próprio JDK está repleto de tais classes (ex: java.util.Collections.SingletonSet<E>está privateem java.util.Collections).
Est

Respostas:

8

Meu entendimento está correto?

Sim.

Quais seriam os motivos válidos para ter modificadores de acesso a membros menos restritivos?

Duas razões:

  • Às vezes, você está implementando uma interface; métodos de interface devem serpublic
  • Isso facilita a alteração do acesso geral da sua turma. Por exemplo, se você marcar todos os métodos que você deseja que sejam públicos public, mesmo em uma classe privada de pacote, mais tarde tudo o que você precisa fazer para tornar a classe pública é adicionar publicà declaração de classe.

Finalmente, quais são as melhores práticas a seguir?

Essa é uma questão de opinião, portanto, não é adequada para uma pergunta ou resposta do Stack Overflow. Faça o que lhe parecer razoável e / ou sua equipe e / ou faça o que o guia de estilo da sua equipe lhe disser.

TJ Crowder
fonte