Control de Acceso y Encapsulamiento Pbc

11

Click here to load reader

Transcript of Control de Acceso y Encapsulamiento Pbc

Page 1: Control de Acceso y Encapsulamiento Pbc

Universidad Los Ángeles de Chimbote Curso: Técnicas de Programación

Docente: Ing. Pedro Beltrán Canessa ~ 1 ~

CONTROL DE ACCESO 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

Page 2: Control de Acceso y Encapsulamiento Pbc

Universidad Los Ángeles de Chimbote Curso: Técnicas de Programación

Docente: Ing. Pedro Beltrán Canessa ~ 2 ~

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.

Page 3: Control de Acceso y Encapsulamiento Pbc

Universidad Los Ángeles de Chimbote Curso: Técnicas de Programación

Docente: Ing. Pedro Beltrán Canessa ~ 3 ~

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:

Page 4: Control de Acceso y Encapsulamiento Pbc

Universidad Los Ángeles de Chimbote Curso: Técnicas de Programación

Docente: Ing. Pedro Beltrán Canessa ~ 4 ~

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

Page 5: Control de Acceso y Encapsulamiento Pbc

Universidad Los Ángeles de Chimbote Curso: Técnicas de Programación

Docente: Ing. Pedro Beltrán Canessa ~ 5 ~

rias veces y e o va contra e princ p o de reu

ENCAPSULAMIENTO

Como se puede observar de los diagramas, las variables del objeto se localizan en el centro o

núcleo del objeto. Los métodos rodean y esconden el núcleo del objeto de otros objetos en el

programa. Al empaquetamiento de las variables de un objeto con la protección de sus métodos

se le llama encapsulamiento. Típicamente, el encapsulamiento es utilizado para esconder

detalles de la puesta en práctica no importantes de otros objetos. Entonces, los detalles de la

puesta en práctica pueden cambiar en cualquier tiempo sin afectar otras partes del programa.

El encapsulamiento de variables y métodos en un componente de software ordenado es,

todavía, una simple idea poderosa que provee dos principales beneficios a los desarrolladores

de software:

Modularidad, esto es, el código fuente de un objeto puede ser escrito, así como darle

mantenimiento, independientemente del código fuente de otros objetos. Así mismo, un

objeto puede ser transferido alrededor del sistema sin alterar su estado y conducta.

Ocultamiento de la información, es decir, un objeto tiene una "interfaz publica" que

otros objetos pueden utilizar para comunicarse con él. Pero el objeto puede mantener

información y métodos privados que pueden ser cambiados en cualquier tiempo sin

afectar a los otros objetos que dependan de ello.

Los objetos proveen el beneficio de la modularidad y el ocultamiento de la información. Las

clases proveen el beneficio de la reutilización. Los programadores de software utilizan la misma

clase, y por lo tanto el mismo código, una y otra vez para crear muchos objetos.

En las implantaciones orientadas a objetos se percibe un objeto como un paquete de datos y

procedimientos que se pueden llevar a cabo con estos datos. Esto encapsula los datos y los

procedimientos. La realidad es diferente: los atributos se relacionan al objeto o instancia y los

métodos a la clase. ¿Por qué se hace así? Los atributos son variables comunes en cada objeto

de una clase y cada uno de ellos puede tener un valor asociado, para cada variable, diferente al

que tienen para esa misma variable los demás objetos. Los métodos, por su parte, pertenecen

a la clase y no se almacenan en cada objeto, puesto que sería un desperdicio almacenar el

mismo procedimiento va ll l i i tilización de código.

Page 6: Control de Acceso y Encapsulamiento Pbc

Universidad Los Ángeles de Chimbote Curso: Técnicas de Programación

Docente: Ing. Pedro Beltrán Canessa ~ 6 ~

Imaginemos que se crea una clase, una docena de programadores tienen acceso a dicha clase

y la utilizan a discreción, posteriormente dicha clase comienza a comportarse de una manera

inesperada debido a que los valores que algunas variables han tomado no fueron anticipados y

todo comienza a desmoronarse. Para corregir el problema se crea una versión más nueva de

dicha clase y listo.

Bueno, a esto le llamamos flexibilidad y capacidad de mantenimiento, ambas son características

y beneficios de la programación Orientada a Objetos (OO) pero para que una clase pueda

cumplir dichas funciones los programadores debemos de hacer algo. Imaginemos que creamos

una clase con variables de instancia públicas a las cuales podemos acceder sin problemas desde

fuera de la misma clase...

public class MiClase{

public int tipo;

}

class AccesoDirecto{

public static void main(String[] args){

MiClase mc = new MiClase();

mc.tipo = -5; //1

}

}

Analizando el código anterior podemos darnos cuenta de que las variables enteras tipo y clase

son públicas y pueden ser accedidas directamente a través de una instancia de la clase MiClase,

esto compila sin ningún problema, digamos que es 'legal', sin embargo, ¿qué pasa si

ingresamos un valor que no se supone debe de tener una variable (en este caso el -5 que le

asignamos a tipo)?, simplemente no hay nada que nos detenga para hacerlo. La única manera

de proteger el código es escribiendo un método que nos permita regular los valores que cada

variable puede tener y escondiendo las variables para que no se pueda acceder a ellas de

manera directa, esto es el principio básico de encapsulamiento.

Si se desea flexibilidad, buen mantenimiento y extensibilidad, nuestro diseño en el código debe

de incluir encapsulamiento, para ello debemos de hacer lo siguiente:

Mantener las variables de instancia protegidas (puede ser con un modificador de acceso,

p.ej., private)

Page 7: Control de Acceso y Encapsulamiento Pbc

Universidad Los Ángeles de Chimbote Curso: Técnicas de Programación

Docente: Ing. Pedro Beltrán Canessa ~ 7 ~

Hacer métodos de acceso públicos para forzar al acceso a las variables por medio de dichos

métodos en lugar de acceder directamente.

Utilizar las convenciones de código para los nombres de los métodos, p. ej., set y get.

El ejemplo anterior modificado para un buen encapsulamiento quedaría así:

public class MiClase{

private int tipo;

public void setTipo(int t){

tipo = t;

}

public int getTipo(){

return tipo;

}

}

class AccesoIndirecto{

public static void main(String[] args){

MiClase mc = new MiClase();

mc.setTipo(5);

System.out.println("El tipo es:" + mc.getTipo());

}

}

Si nos fijamos un poquito, en el método setTipo() no existen validaciones para prevenir que un

valor no válido sea asignado a la variable, sin embargo, el proveer de un método de este tipo

desde el diseño inicial de la aplicación nos permite posteriormente modificar el comportamiento

de la misma sin afectar los métodos utilizados, tal vez en un futuro se desee que dicha variable

solamente pueda tener uno entre un rango de valores y se podrán aplicar posteriormente los

cambios sin que haya repercusiones negativas.

Page 8: Control de Acceso y Encapsulamiento Pbc

Universidad Los Ángeles de Chimbote Curso: Técnicas de Programación

Docente: Ing. Pedro Beltrán Canessa ~ 8 ~

THIS Al acceder a variables de instancia de una clase, la palabra clave this hace referencia a los

miembros de la propia clase en el objeto actual; es decir, this se refiere al objeto actual sobre el

que está actuando un método determinado y se utiliza siempre que se quiera hace referencia al

objetoactual de la clase. Volviendo al ejemplo de MiClase, se puede añadir otro constructor de

la forma siguiente:

public class MiClase {

int i;

public MiClase() {

i = 10;

}

// Este constructor establece el valor de i

public MiClase( int valor ) {

this.i = valor; // i = valor

}

// Este constructor también establece el valor de i

public MiClase( int i ) {

this.i = i;

}

public void Suma_a_i( int j ) {

i = i + j;

}

}

Aquí this.i se refiere al entero i en la clase MiClase, que corresponde al objeto actual. La

utilización de this en el tercer constructor de la clase, permite referirse directamente al objeto

en sí, en lugar de permitir que el ámbito actual defina la resolución de variables, al utilizar i

como parámetro formal y después this para acceder a la variable de instancia del objeto actual.

La utilización de this en dicho contexto puede ser confusa en ocasiones, y algunos

programadores procuran no utilizar variables locales y nombres de parámetros formales que

ocultan variables de instancia. Una filosofía diferente dice que en los métodos de inicialización y

constructores, es bueno seguir el criterio de utilizar los mismos nombres por claridad, y utilizar

this para no ocultar las variables de instancia. Lo cierto es que es más una cuestión de gusto

personal que otra cosa el hacerlo de una forma u otra.

La siguiente aplicación de ejemplo, utiliza la referencia this al objeto para acceder a una

variable de instancia oculta para el método que es llamado.

Page 9: Control de Acceso y Encapsulamiento Pbc

Universidad Los Ángeles de Chimbote Curso: Técnicas de Programación

Docente: Ing. Pedro Beltrán Canessa ~ 9 ~

class javathis {

// Variable de instancia

int miVariable;

// Constructor de la clase

public javathis() {

miVariable = 5;

}

// Metodo con argumentos

void miMetodo(int miVariable) {

System.out.println( "La variable Local miVariable contiene " + miVariable );

System.out.println( "La variable de Instancia miVariable contiene " + this.miVariable );

}

public static void main( String args[] ) {

// Instanciamos un objeto del tipo de la clase

javathis obj = new javathis();

// que utilizamos para llamar a su unico metodo

obj.miMetodo( 10 );

}

}

SUPER

Si se necesita llamar al método padre dentro de una clase que ha reemplazado ese método, se

puede hacer referencia al método padre con la palabra clave super:

import MiClase;

public class MiNuevaClase extends MiClase {

public void Suma_a_i( int j ) {

i = i + ( j/2 );

super.Suma_a_i( j );

}

}

Page 10: Control de Acceso y Encapsulamiento Pbc

Universidad Los Ángeles de Chimbote Curso: Técnicas de Programación

Docente: Ing. Pedro Beltrán Canessa ~ 10 ~

En el siguiente código, el constructor establecerá el valor de i a 10, después lo cambiará a 15 y

finalmente el método Suma_a_i() de la clase padre MiClase lo dejará en 25:

MiNuevaClase mnc;

mnc = new MiNuevaClase();

mnc.Suma_a_i( 10 );

Super es un concepto que no existe en C++, al menos no con una implementación similar a

Java. Si un método sobreescribe un método de su superclase, se puede utilizar la palabra clave

super para eludir la versión sobreescrita de la clase e invocar a la versión original del método

en la supreclase. Del mismo modo, se puede utilizar super para acceder a variables miembro de

la superclase.

En el ejemplo, la aplicación utiliza super para referirse a una variable local en un método y a

una variable de la superclase que tiene el mismo nombre. El programa también utiliza super

para invocar al constructor de la superclase desde en constructor de la subclase.

/**

* Este ejemplo muestra el uso del puntero "super" para acceder

* al constructor de la clase padre. Tambien ilustra el uso de

* "super" para resolver la ambiguedad entre las variables

* local y de instancia en la superclase

*/

class base {

int datoBase;

public base() {

System.out.print( "Dentro del Constructor de la clase base" );

System.out.println( "Asignando a datoBase 100" );

datoBase = 100;

}

} class javasuper extends base {

int datoSubClase;

// Constructor de la Subclase

Page 11: Control de Acceso y Encapsulamiento Pbc

Universidad Los Ángeles de Chimbote Curso: Técnicas de Programación

Docente: Ing. Pedro Beltrán Canessa ~ 11 ~

public javasuper() {

// Llamada al constructor de la clase base

super();

System.out.print( "Dentro del Constructor de la subclase" );

System.out.println( "Asignando a datoSubClase 200" );

datoSubClase = 200;

}

// Metodo para mostrar como se resuelve la ambiguedad entre

// una variable local y una variable de instancia que tienen

// el mismo nombre

void miMetodo() {

// Se crea una variable local para ocultar la variable de

// instancia de la clase base

int datoBase = 300;

System.out.println( "Dentro del metodo miMetodo" ); System.out.println( "El

valor de la variable Local es " + datoBase ); System.out.println( "El valor de la

variable de Instancia es "+ super.datoBase );

}

public static void main( String args[] ) {

javasuper obj = new javasuper();

System.out.println( "Dentro de main" );

System.out.println( "La variable de instancia en la clase contiene " + obj.datoBase);

System.out.println( "La variable de instancia en la subclase contiene "+obj.datoSubClase);

// Llamada al metodo para mostrar el uso de super en la

// resolucion de la ambiguedad

obj.miMetodo();

}

}