lunes, 22 de octubre de 2012

Controlar el Acceso a los Miembros de la Clase


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