En C++ el control de acceso es menos
complicado que en Java. Cualquier miembro individual de una clase en C++, puede ser
designado como: private, public o protected. Un miembro private solamente puede ser accedido por
otros miembros de la propia clase; no puede ser accedido por miembros de una clase
heredada. Es la designación más restrictiva de todas.
Un miembro designado como public
puede ser accedido desde cualquier código dentro del ámbito de un objeto instanciado a
partir de la clase. Es la designación menos restrictiva.
La designación de protected
entra en juego solamente cuando se ve involucrada la herencia. Un miembro designado como protected
aparece como public para los miembros de clases derivadas de la clase y aparece
como private para todas las demás.
En C++ hay un segundo nivel de control de
acceso con las mismas palabras reservadas, que no tiene analogía en Java, y que se aplica
a nivel de la herencia de una clase desde otra clase.
También en C++, hay un aspecto adicional que
son las funciones friend de una clase. Estas funciones tienen acceso a todos
los miembros privados y protegidos de esa clase. Esta función puede ser una función
miembro de otra clase o simplemente una función aislada (que no está soportada en Java).
Java no tiene nada semejante a las funciones friend de C++.
El control de acceso se aplica siempre a nivel
de clase, no a nivel de objeto. Es decir, los métodos de instancia de un objeto de una
clase determinada tienen acceso directo a los miembros privados de cualquier otro objeto
de la misma clase.
En Java, el control de acceso se complica un
poco por la inclusión de la noción de package (paquete). Java implementa
los mismos tres especificadores de acceso que C++ (aunque no necesariamente con el mismo
significado) y, además, implementa ese cuarto especificador si no se ha indicado ninguno
de los otros tres, que es el definido como package, default o friendly.
Por lo tanto, cuando se crea una nueva clase en
Java, se puede especificar el nivel de acceso que se quiere para las variables de
instancia y los métodos definidos en la clase: private, protected, public
y package.
La tabla siguiente muestra el nivel de acceso
que está permitido a cada uno de los especificadores:
Nivel
de Acceso |
clase |
subclase |
paquete |
todos |
Private |
X |
|
|
|
Protected |
X |
X* |
X |
|
Public |
X |
X |
X |
X |
Package |
X |
|
X |
|
Si se profundiza en el
significado de la tabla, se puede observar que la columna clase indica que
todos los métodos de una clase tienen acceso a todos los otros miembros de la misma
clase, independientemente del nivel de acceso especificado.
La columna subclase se aplica a
todas las clases heredadas de la clase, independientemente del paquete en que residan. Los
miembros de una subclase tienen acceso a todos los miembros de la superclase que se hayan
designado como public. El asterisco (*) en la intersección subclase-protected quiere
decir que si una clase es a la vez subclase y está en el mismo paquete que la clase con
un miembro protected, entonces la clase tiene acceso a es miembro protegido.
En general, si la subclase no se encuentra en
el mismo paquete que la superclase, no tiene acceso a los miembros protegidos de la
superclase. Los miembros de una subclase no tienen acceso a los miembros de la superclase
catalogados como private o package, excepto a los miembros de una subclase
del mismo paquete, que tienen acceso a los miembros de la superclase designados como package.
La columna paquete indica que las
clases del mismo paquete tienen acceso a los miembros de una clase, independientemente de
su árbol de herencia. La tabla indica que todos los miembros protected, public
y package de una clase pueden ser accedidos por otra clase que se encuentre en el
mismo paquete. Esto puede asemejarse un poco a la designación de funciones friend
en C++, salvando las diferencias, que no son pocas.
En C++, se puede calificar un método en una
clase diferente como friend de una clase determinada y ese status de friend no se
extiende a ningún otro método de la clase, es decir, una persona de otra familia puede
ser tu amigo, pero no por eso tienen que ser tus amigos el resto de los miembros de la
familia de tu amigo.
En Java, colocando dos o más clases en el
mismo paquete se hace que la relación friend, de amistad, se extienda a todos los
métodos de las clases, es decir, si eres amigo de uno de los miembros de una familia,
serás amigo automáticamente de todos y cada uno de los componentes de esa familia.
La columna todos indica que los
privilegios de acceso para métodos que no están en la misma clase, ni en una subclase,
ni en el mismo paquete, se encuentran restringidos a los miembros públicos de la clase.
Si se observa la misma tabla desde el punto de
vista de las filas, podemos describir los calificadores de los métodos.
private
private String NumeroDelCarnetDeIdentidad;
Las variables y métodos de instancia privados
sólo pueden ser accedidos desde dentro de la clase. No son accesibles desde las subclases
de esa clase. Hay que resaltar una vez más, que un método de instancia de un objeto de
una clase puede acceder a todos los miembros privados de ese objeto, o miembros privados
de cualquier otro objeto de la misma clase. Es decir, que en Java el control de acceso
existe a nivel de clase, pero no a nivel de objeto de la clase.
public
public void CualquieraPuedeAcceder(){}
Cualquier clase desde cualquier lugar puede
acceder a las variables y métodos de instancia públicos.
protected
protected void SoloSubClases(){}
Sólo las subclases de la clase y nadie más
puede acceder a las variables y métodos de instancia protegidos. Los métodos protegidos
pueden ser vistos por las clases derivadas, como en C++, y también, en Java, por los
paquetes. Todas las clases de un paquete pueden ver los métodos protegidos de ese
paquete. Esto difiere significativamente de C++, en donde los miembros protegidos
solamente pueden ser accedidos por miembros de la misma clase o miembros de subclases.
package
(fiendly, sin declaración
específica)
void MetodoDeMiPaquete(){}
Por defecto, si no se especifica el control de
acceso, las variables y métodos de instancia se declaran package (friendly,
amigas), lo que significa que son accesibles por todos los objetos dentro del mismo
paquete, pero no por los externos al paquete. Aparentemente, parece lo mismo que protected;
la diferencia estriba en que la designación de protected es heredada por las
subclases de un paquete diferente, mientras que la designación package no es
heredada por subclases de paquetes diferentes.
Debido a la complejidad y posible confusión
respecto a los niveles de protección que proporciona Java para permitir el control
preciso de la visibilidad de variables y métodos, se puede generar otra tabla en base a
cuatro categorías de visibilidad entre los elementos de clase:
|
private |
sin
modificador |
protected |
public |
Misma clase |
SI |
SI |
SI |
SI |
Misma subclase de paquete |
NO |
SI |
SI |
SI |
Misma no-subclase de paquete |
NO |
SI |
SI |
SI |
Subclase de diferente paquete |
NO |
NO |
SI |
SI |
No-subclase de diferente paquete |
NO |
NO |
NO |
SI |
Y una guía de uso indicaría
tener en cuenta lo siguiente:
- Usar private para métodos y
variables que solamente se utilicen dentro de la clase y que deberían estar ocultas para
todo el resto
- Usar public para métodos, constantes y otras variables importantes que deban ser
visibles para todo el mundo
- Usar protected si se quiere que las clases del mismo paquete puedan tener acceso
a estas variables o métodos
- Usar la sentencia package para poder agrupar las clases en paquetes
- No usar nada, dejar la visibilidad por defecto (default, package) para
métodos y variables que deban estar ocultas fuera del paquete, pero que deban estar
disponibles al acceso desde dentro del mismo paquete. Utilizar protected en su
lugar si se quiere que esos componentes sean visibles fuera del paquete
|