Modificador de Acceso: Private y Public en Java

Buenos días, en esta entrada y en algunas mas hablaremos sobre los modificacodres de acceso en en los miembros de la clase. Este tema es bastante largo ya que contiene varios modificadores, junto a su uso, cosas a tener muy en cuenta, y características mas importantes.


Modificadores de Acceso:

Dado que tanto a los métodos como a las variables miembro se les da un control de acceso de la misma manera, veremos esto a continuación.

Mientras que una clase solo tiene 2 miembros de acceso (public y por defecto), los miembros pueden tener 4 diferentes:

  • public
  • protected
  • default
  • private

La protección por defecto es la que damos cuando no ponemos ningún modificador de acceso en la declaración del miembro. El control de acceso “default” y “protected” tienen casi un comportamiento idéntico, excepto por una diferencia que veremos después.

¿Qué significa que el código de una clase tiene acceso al miembro de otra clase?; Por ahora vamos a ignorar cualquier diferencia entre métodos y variables. Si una clase A tiene acceso a un miembro de la clase B, esto significa que el miembro de la clase B es visible a la clase A.

Tenemos que entender 2 cuestiones diferentes:

  • Si el código del método con una clase puede acceder a un miembro de otra clase.
  • Si la subclase puede heredar un miembro de la superclase.

El primer tipo de acceso es cuando el método en una clase intenta acceder a un método o a una variable de otra clase, usando el operador (.) para invocar al método o recuperar una variable.

Por ejemplo:

		class Zoo{
			public String coolMethod(){
				return "Wow Baby";
			}
		}
		
		class Moo{
			public void useAZoo(){
				Zoo z = new Zoo();
				//Si la anterior línea compila, Moo tiene acceso
				//a la clase >oo
				//Pero...¿Tendrá acceso al método coolMethod()?
				System.out.println("A Zoo says " + z.coolMethod());
				//Funciona porque tiene acceso
			}
		}
		

El segundo tipo de acceso gira entorno a si alguno de los miembros de una superclase a la que una subclase puede acceder a través de la herencia. Estamos viendo si una subclase hereda un miembto de la superclase. Recordamos, que si una subclase hereda un miembro, es exactamente como si la subclase declarara el miembro por sí mismo:

		class Zoo {
			public String coolMethod(){
				return "Wow baby";
			}
		}

		class Moo extends Zoo{
			public void useMyCoolMethod(){
				// ¿Hará la herencia de Moo una instancia del método coolMethod()?
				System.out.println("Moo says, " + this.coolMethod());
				//El código anterior funciona porque Moo ha heredado el método publico
				//¿Podrá una instancia de Moo invocar el método coolMethod() en una instancia de Zoo?
				Zoo z = new Zoo();
				System.out.println("Zoo says, " + z.coolMethod());
				//coolMethod() es público, por lo que Moo puede invocarlo en una referencia a Zoo
			}
		}
		
  • Miembros Public

    Cuando un método o una variable miembro es declarada como public, esto significa que todas las clases, sin importar el paquete al que pertenece, puede acceder al miembro

    Miremos el siguiente ejemplo:

    			package book;
    			import cert.*;
    			
    			class Goo {
    				public static void main (String[] args){
    					Sludge o = new Sludge();
    					o.testIt();
    				}
    			}
    			

    Ahora miremos el otro archivo:

    			package cert;
    
    			public class Sludge {
    				public void testIt(){
    					System.out.println("Sludge");
    				}
    			}
    			

    Como podemos ver, Goo y Sludge están en diferentes paquetes. Sin embargo, Goo puede invocar el método de Sludge sin problemas porque tanto como la clase Sludge como su método están marcados como public.

    Para una subclase, si un miembro de su superclase es declarada public, la subclase hereda al miembro sin importar que ambas clases estén en el mismo paquete.

    			package cert;
    
    			public class Roo {
    				public String doRooThings(){
    					//Aquí el código
    					return "Fun";
    				}
    			}
    			
    			package notcert;
    			import cert.Roo;
    			
    			class Cloo extends Roo{
    				public void testClass(){
    					System.out.println(doRooThings());
    				}
    			}
    			

    Recordamos que si usamos la llamada a un método sin el operador (.) quiere decir que estamos llamando o accediendo a un método que pertenece a la clase que estamos viendo. Si se usa this., quiere decir que hacemos referencia al objeto que se está ejecutando en ese momento.

  • Miembros Private

    Los miembros marcados como private no pueden ser accedidos por código de otra clase, excepto por la clase en la que fueron declarados. Vamos a realizar un pequeño cambio a la clase Roo que vimos antes:

    			package cert;
    
    			public class Roo {
    				private String doRooThings(){
    					//Aquí el código pero que solo esta clase puede conocer
    					return "Fun";
    				}
    			}
    			

    El método doRooThings() es ahora privado, por lo que ninguna clase puede usarlo.

    			package notcert;
    			import cert.Roo;
    			class UseARoo {
    				public void testIt(){
    					Roo r = new Roo();
    					System.out.println(r.doRooThings()); //Error de compilación
    				}
    			}
    			

    El error que nos resulta es como si el método doRooThings() no existiera, y para el código que no esté en la clase Roo, esto es así. Un miembro privado es invisible para cualquier código fuera de la clase del miembro.

    ¿Que pasa si una subclase hereda un miembro privado de la superclase? Cuando un miembro es declarado private, la subclase no puede heredarlo. Una subclase no puede ver, usar o hacer nada con el miembro privado de la superclase. Podemos, sin embargo, declarar un método que se llame igual en la subclase. Sin tener en cuenta lo que parezca, NO ES SUSTITUIR EL MËTODO. Es tan simple como un método que tiene el mismo nombre que el método privado de la superclase. Las reglas de sustituir el método no se aplican, y podemos hacer lo que queramos con este nuevo método, añadir otras excepciones, cambiar el valor de retorno, etc.

    			package cert;
    
    			public class Roo {
    				private String doRooThings(){
    					//Código
    					return "Fun";
    				}
    			}
    			

    El método doRooThings() está fuera del alcance de todas las subclases, aunque estén en el mismo paquete que la superclase:

    			package cert;
    
    			class Cloo extends Roo{
    				public void testCloo(){
    					System.out.println(doRooThings()); //Error al compilar
    				}
    			}
    			

    ¿Puede un método privado ser sustituido por una subclase? Es una pregunta interesante, pero la respuesta es técnicamente, NO. Como la subclase, como hemos visto, no puede heredar un método privado entonces no puede sustituir al método.

Hasta aquí estos 2 modificadores de acceso, que nos explican un poco su funcionamiento mas común y sirva para aclarar dudas.

Cualquier aporte o corrección son bienvenidos.

Saludos!!!