Controlar el Acceso a los Miembros de la Clase
Uno de los beneficios de las clases es
que pueden proteger sus variables y métodos miembros frente al acceso de otros
objetos. ¿Por qué es esto importante? Bien, consideremos esto. Se ha escrito
una clase que representa una petición a una base de datos que contiene toda
clase de información secreta, es decir, registros de empleados o proyectos
secretos de la compañía.
Ciertas informaciones y peticiones
contenidas en la clase, las soportadas por los métodos y variables accesibles
públicamente en su objeto son correctas para el consumo de cualquier otro objeto
del sistema. Otras peticiones contenidas en la clase son sólo para el uso
personal de la clase. Estas otras soportadas por la operación de la clase no
deberían ser utilizadas por objetos de otros tipos. Se querría proteger esas
variables y métodos personales a nivel del lenguaje y prohibir el acceso desde
objetos de otros tipos.
En Java se puede utilizar los
especificadores de acceso para proteger tanto las variables como los métodos de
la clase cuando se declaran. El lenguaje Java soporta cuatro niveles de acceso
para las variables y métodos miembros: private, protected, public, y, todavía
no especificado, acceso de paquete.
La
siguiente tabla le muestra los niveles de acceso pemitidos por cada
especificador:
Especificador
clase subclase paquete mundo
private
X
protected
X
X* X
public
X X X X
package
X X
La
primera columna indica si la propia clase tiene acceso al miembro definido por
el especificador de acceso. La segunda columna indica si las subclases de la clase
(sin importar dentro de que paquete se encuentren estas) tienen acceso a los
miembros. La tercera columna indica si las clases del mismo paquete que la
clase (sin importar su parentesco) tienen acceso a los miembros. La cuarta
columna indica si todas las clases tienen acceso a los miembros.
Observa
que la intersección entre protected y subclase tiene un '*' - este caso de
acceso particular tiene una explicación en más detalle más
adelante.
Echemos un vistazo a cada uno de los
niveles de acceso más detalladamente:
Private
El nivel de acceso más restringido es
private. Un miembro privado es accesible sólo para la clase en la que está
definido. Se utiliza este acceso para declarar miembros que sólo deben ser
utilizados por la clase. Esto incluye las variables que contienen información que
si se accede a ella desde el exterior podría colocar al objeto en un estado de inconsistencia,
o los métodos que llamados desde el exterior pueden ponen en peligro el estado
del objeto o del programa donde se está ejecutando. Los miembros privados son como
secretos, nunca deben contársele a nadie.
Para declarar un miembro privado se
utiliza la palabra clave private en su declaración.
La clase siguiente contiene una
variable miembro y un método privados:
class Alpha {
private int soyPrivado;
private void metodoPrivado() {
System.out.println("metodoPrivado");
}
}
Los objetos del tipo Alpha pueden
inspeccionar y modificar la variable soyPrivado y pueden invocar el
método metodoPrivado(), pero los objetos de otros tipos no pueden acceder.
Por ejemplo, la clase Beta definida aquí:
class Beta {
void metodoAccesor() {
Alpha a = new Alpha();
a.soyPrivado = 10; // ilegal
a.metodoPrivado(); // ilegal
}
}
No puede acceder a la variable soyPrivado
ni al método metodoPrivado() de un objeto del tipo Alpha porque Beta
no es del tipo Alpha.
Si una clase está intentando acceder a
una variable miembro a la que no tiene acceso--el compilador mostrará un
mensaje de error similar a este y no compilará su programa:
Beta.java:9: Variable
iamprivate in class Alpha not accessible from class Beta.
a.iamprivate = 10; // ilegal
^
1 error
Y si un programa intenta acceder a un
método al que no tiene acceso, generará un error de compilación parecido a
este:
Beta.java:12: No method
matching privateMethod() found in class Alpha.
a.privateMethod();
// ilegal
1 error
Protected
El siguiente especificador de nivel de
acceso es 'protected' que permite a la propia clase, las subclases (con la
excepción a la que nos referimos anteriormente), y todas las clases dentro del
mismo paquete que accedan a los miembros. Este nivel de acceso se utiliza cuando
es apropiado para una subclase da la clase tener acceso a los miembros, pero no
las clases no relacionadas. Los miembros protegidos son como secretos
familiares - no importa que toda la familia lo sepa, incluso algunos amigos
allegados pero no se quiere que los extraños lo sepan.
Para declarar un miembro protegido, se
utiliza la palabra clave protected. Primero echemos un vistazo a cómo afecta
este especificador de acceso a las clases del mismo paquete.
Consideremos esta versión de la clase
Alpha que ahora se declara para estar incluida en el paquete Griego y que tiene
una variable y un método que son miembros protegidos:
package Griego;
class Alpha {
protected int estoyProtegido;
protected void metodoProtegido() {
System.out.println("metodoProtegido");
}
}
Ahora, supongamos que la clase Gamma,
también está declarada como miembro del paquete Griego (y no es una subclase de
Alpha). La Clase Gamma puede acceder legalmente al miembro estoyProtegido del
objeto Alpha y puede llamar legalmente a su método metodoProtegido():
package
Griego;
class
Gamma {
void metodoAccesor() {
Alpha a = new Alpha();
a.estoyProtegido = 10;
// legal
a.metodoProtegido(); //
legal
}
}
Esto es muy sencillo. Ahora,
investiguemos cómo afecta el especificador portected a una subclase de Alpha.
Introduzcamos una nueva clase, Delta,
que desciende de la clase Alpha pero reside en un paquete diferente - Latin. La
clase Delta puede acceder tanto a estoyProtegido como a metodoProtegido(),
pero solo en objetos del tipo Delta o sus subclases. La clase Delta no puede
acceder a estoyProtegido o metodoProtegido() en objetos del tipo
Alpha. metodoAccesor() en el siguiente ejemplo intenta acceder a la
variable miembro estoyProtegido de un objeto del tipo Alpha, que es
ilegal, y en un objeto del tipo Delta que es legal. Similarmente, metodoAccesor()
intenta invocar a metodoProtegido() en un objeto del tipo Alpha, que
también es ilegal:
import Griego.*;
package Latin;
class Delta extends
Alpha {
void metodoAccesor(Alpha a,
Delta d) {
a.estoyProtegido = 10; // ilegal
d.estoyProtegido = 10; // legal
a.metodoProtegido(); // ilegal
d.metodoProtegido(); // legal
}
}
Si una clase es una subclase o se cuenta
en el mismo paquete de la clase con el miembro protegido, la clase tiene acceso
al miembro protegido.
Public
El especificador de acceso más
sencillo es 'public'. Todas las clases, en todos los paquetes tienen acceso a
los miembros públicos de la clase. Los miembros públicos se declaran sólo si su
acceso no produce resultados indeseados si un extraño los utiliza.
Aquí no hay secretos familiares; no
importa que lo sepa todo el mundo.
Para declarar un miembro público se
utiliza la palabra clave public. Por ejemplo,
package Griego;
class Alpha {
public int soyPublico;
public void metodoPublico() {
System.out.println("metodoPublico");
}
}
Reescribamos nuestra clase Beta una
vez más y la ponemos en un paquete diferente que la clase Alpha y nos
aseguramos que no están relacionadas (no es una subclase) de Alpha:
import Griego.*;
package Romano;
class Beta {
void metodoAccesor() {
Alpha a = new Alpha();
a.soyPublico = 10; // legal
a.metodoPublico(); // legal
}
}
Como se puede ver en el ejemplo
anterior, Beta puede inspeccionar y modificar legalmente la variable soyPublico
en la clase Alpha y puede llamar legalmente al método metodoPublico().
Acceso
de Paquete
Y finalmente, el último nivel de
acceso es el que se obtiene si no se especifica ningún otro nivel de acceso a
los miembros. Este nivel de acceso permite que las clases del mismo paquete que
la clase tengan acceso a los miembros. Este nivel de acceso asume que las
clases del mismo paquete son amigas de confianza. Este nivel de confianza es como
la que extiende a sus mejores amigos y que incluso no la tiene con su familia.
Por ejemplo, esta versión de la clase
Alpha declara una variable y un método con acceso de paquete. Alpha reside en
el paquete Griego:
package Griego;
class Alpha {
int estoyEmpaquetado;
void metodoEmpaquetado() {
System.out.println("metodoEmpaquetado");
}
}
La clase Alpha tiene acceso a estoyEmpaquetado
y a metodoEmpaquetado().
Además, todas las clases declaradas
dentro del mismo paquete como Alpha también tienen acceso a estoyEmpaquetado y metodoEmpaquetado().
Supongamos que tanto Alpha como Beta son declaradas como parte del paquete
Griego:
package Griego;
class Beta {
void metodoAccesor() {
Alpha a = new Alpha();
a.estoyEmpaquetado = 10; //
legal
a.metodoEmpaquetado(); // legal
}
}
Entonces Beta puede acceder legalmente
a estoyEmpaquetado y metodoEmpaquetado().
No hay comentarios:
Publicar un comentario