SCJP for JSE5 - 5
Posted on mayo 26, 2007 by Carlos Alexander Zuluaga
1. DECLARACIÓN DE MÉTODOS Y ATRIBUTOS (MIEMBROS)
Los atributos y métodos de las clases tienen siempre un nivel de acceso aunque éste no sea digitado. Existen cuatro niveles: public, protected, default y private, cada uno de ellos restringiendo o permitiendo el acceso a los miembros de las clases, pero, es muy importante saber que si una clase no puede "ver" a la otra, mucho menos podrá ver sus miembros; esto ocurre en el caso de una clase con modificador de acceso default (cuando no se digita nada) que se intenta acceder desde una clase en un paquete diferente. Por ejemplo:
package uno;
class Servidor{
//muchos métodos y atributos
}
package dos;
public class Cliente{
//otro montón de métodos tratando de acceder a Servidor
}
En este caso no importan los modificadores de acceso de los miembros de la clase Servidor, por tener esta el tipo de acceso por defecto (default), la clase Cliente nunca podrá acceder a sus atributos o métodos, a menos claro, que se modifiquen para pertenecer al mismo paquete.
Una clase solo puede invocar los métodos o ver los valores de los atributos de otra, cuando ésta última es pública o se encuentran en el mismo paquete, ahí si empiezan a aplicar los modificadores de acceso de los miembros.
Miembros public
Los miembros marcados como public pueden ser accedidos desde cualquier otra clase a través de una instancia o por herencia.
Ejemplo:
package utilidades;
public class Sumas {
public int sumar(int num1, int num2){
return num1 + num2;
}
}
package operaciones;
import utilidades.Sumas;
//nivel de acceso default
class AlgoRaro {
public void realizarCalculosCientificos(){
Sumas s = new Sumas();
//acceso a través de una instancia
int resultado = s.sumar(4,4);
System.out.println("El resultado es: " + resultado);
}
}
En este ejemplo la clase AlgoRaro puede acceder el método sumar() de la clase Sumas por que aunque están en diferentes paquetes la clase Sumas es pública al igual que el método sumar(), y el acceso se hace a través de una instancia de la clase. Lo contrario no se podría hacer, es decir, la clase Sumas no tiene acceso a ninguno de los métodos o atributos de la clase AlgoRaro por que están en diferente paquete y AlgoRaro tiene acceso por defecto, lo que descarta de una vez cualquier tipo de visibilidad.
Miembros private
Los miembros private solo pueden ser accedidos por la clase a la que pertenecen, de ninguna forma (claro, que las hay las hay: reflection) se pueden invocar desde clases externas.
Ejemplo (modificando el anterior):
package utilidades;
public class Sumas {
private int sumar(int num1, int num2){
return num1 + num2;
}
void cualquierOtraCosa(){
int valor = sumar(1,2); //se puede
}
}
package operaciones;
import utilidades.Sumas;
class AlgoRaro {
public void realizarCalculosCientificos(){
Sumas s = new Sumas();
int resultado = s.sumar(4,4); //error de compilación!!!
System.out.println("El resultado es: " + resultado);
}
}
En este caso, la clase AlgoRaro no puede acceder al método sumar() por que es privado, en cambio, el método cualquierOtraCosa() si puede invocarlo por que pertenece a la misma clase.
Miembros default
Los miembros con nivel de acceso default pueden ser accedidos solo por clases que pertenezcan al mismo paquete de la clase que los contiene:
package package1;
public class Valores {
final double PI = 3.14159;
}
package package1;
public class Circunferencia {
public double calcularArea(double radio){
Valores v = new Valores();
return v.PI * radio * radio;
}
}
El atributo de instancia PI, puede ser accedido por la clase Circunferencia por que se encuentran en el mismo paquete, sin embargo:
package package2;
public class Circunferencia {
public double calcularArea(double radio){
Valores v = new Valores();
return v.PI * radio * radio; //Error de compilación!!
}
}
Arroja un error de compilación por que los paquetes son diferentes.
Miembros protected
El nivel de acceso protected es el más particular: una clase puede acceder a los miembros protected de otra si pertenece al mismo paquete o hereda de ella. En el primer caso accede a través de una instancia y el el segundo se invoca directamente. Es decir, el nivel de acceso protected es el mismo default + herencia.
Dada la clase:
package package2;
public class ClaseConMiembroProtegido {
protected String demeAlgo(){
return "Tome un 5";
}
}
El método demeAlgo() se puede acceder a través de una instancia si la clase pertenece al mismo paquete:
package package2;
class AccesoPorPaquete{
void accederAUnMiembro(){
ClaseConMiembroProtegido cc = new ClaseConMiembroProtegido();
System.out.println(cc.demeAlgo());
}
}
O se puede invocar a través de la herencia, simplemente digitando el nombre del método, pertenezca o no al mismo paquete:
package package1;
import package2.ClaseConMiembroProtegido;
class AccesoPorHerencia extends ClaseConMiembroProtegido{
void accederPorHerencia(){
System.out.println("Accediendo por herencia: " + demeAlgo());
}
}
Ojo!!, nos podemos llevar una sorpresa si en el segundo caso intentamos acceder el método demeAlgo() a través de una instancia:
package package1;
import package2.ClaseConMiembroProtegido;
class AccesoPorHerencia extends ClaseConMiembroProtegido{
void accederPorHerencia(){
ClaseConMiembroProtegido cc = new ClaseConMiembroProtegido();
System.out.println("Accediendo por herencia: " + cc.demeAlgo());
//error de compilación!!!
}
}
Esto sucede por que la clase AccesoPorHerencia no pertenece al mismo paquete de ClaseConMiembroProtegido y solo puede acceder sus miembros a través de la herencia.
El Final
Esto es todo en cuando a modificadores de acceso para los miembros de las clases. Es uno de los temas que más claros hay que tener, pues en el examen hay muchas preguntas alrededor y la "flexibilidad" de todo esto, es un punto que juega en nuestra contra.