¿Cuál es el uso de modificadores de acceso de miembros menos restrictivos que el modificador de acceso de clase?

9

Digamos que tengo una clase con algunos miembros, y los miembros tienen un modificador de acceso menos restrictivo que la clase misma.

Un ejemplo concreto podría ser:

package apples;

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

Según tengo entendido, un modificador de acceso de clase que es más restrictivo que el modificador de acceso de miembro , anulará los modificadores de acceso de miembro menos restrictivos . Por lo tanto, un modificador de acceso de miembros menos restrictivo no debería tener ningún efecto.

  • ¿Es correcto mi entendimiento?
    • Si no, ¿cuáles son las consecuencias?
  • ¿Cuáles podrían ser razones válidas para tener modificadores de acceso de miembros menos restrictivos?
  • Finalmente, ¿cuáles son las mejores prácticas a seguir?

También experimenté un poco porque pensé que podría tener consecuencias una vez que comience a pasar referencias de funciones, sin embargo, incluso entonces el modificador de acceso no parece importar.

La situación que construí es la siguiente:

  • apples.Bproporciona un método público bla()que devuelve una referencia a apples.A.foo.
  • Luego pizzas.Cllama apples.B.blapara obtener una referencia A.fooy lo llama.
  • Por A.foo()lo tanto, no es directamente visible para C, pero solo es indirectamente accesible a través deB.bla()

Lo probé y no hace ninguna diferencia si hago que el modificador de acceso del foo() paquete sea privado o no.

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.
fuente
2
La razón más común para este tipo de diseño es proporcionar implementaciones de métodos API públicos (como los de interfaces o clases abstractas extendidas) utilizando clases no públicas. El JDK en sí está repleto de tales clases (por ejemplo: java.util.Collections.SingletonSet<E>está privateen java.util.Collections).
ernest_k

Respuestas:

8

¿Es correcto mi entendimiento?

Si.

¿Cuáles podrían ser razones válidas para tener modificadores de acceso de miembros menos restrictivos?

Dos razones:

  • A veces, estás implementando una interfaz; los métodos de interfaz deben serpublic
  • Hace que sea más fácil cambiar el acceso general de su clase. Por ejemplo, si marca todos los métodos que quisiera que fueran públicos public, incluso en una clase de paquete privado, entonces todo lo que tiene que hacer para hacer que la clase sea pública es agregar publica la declaración de clase.

Finalmente, ¿cuáles son las mejores prácticas a seguir?

Esa es una cuestión de opinión, por lo que no es adecuada para una pregunta o respuesta de Stack Overflow. Haga lo que le parezca razonable a usted y / o su equipo, y / o haga lo que la guía de estilo de su equipo le dice que haga.

TJ Crowder
fuente