Programación interactiva Oscar Bedoya [email protected] Encapsulamiento Encapsulamiento • El encapsulamiento es la propiedad que permite envolver atributos (datos) y métodos (comportamiento) en un unidad lógica, el objeto • Se encapsulan (envuelven) atributos y métodos de una clase Encapsulamiento • El radio de un auto encapsula sus datos y el comportamiento que le permiten al conductor seleccionar una estación de radio, reproducir CD’s, entre otras acciones. •Los componentes del radio están encapsulados en su caja Encapsulamiento • El encapsulamiento permite a los objetos ocultar su implementación de otros objetos, este principio se conoce como ocultamiento de la información • Aunque los objetos se pueden comunicar entre si a través de interfaces, no están conscientes de cómo se implementan otros objetos •Los detalles de implementación se ocultan dentro de los mismos objetos (buena ingeniería de software!!!) Encapsulamiento • Cómo se logra encapsular atributos y métodos en Java? •Utilizando modificadores de acceso Modificador de acceso public private Descripción Las variables o métodos declarados como public se pueden utilizar en cualquier parte de la clase. Además, se puede hacer referencia a ellos desde un objeto directamente Las variables o métodos declarados como private solo pueden ser utilizados por los métodos de la clase en la que están declarados. Para hacer referencia a las variables private desde un objeto, se debe hacer por medio de un método get (interfaz) Encapsulamiento Empleado - UsoEmpleado Encapsulamiento • Las variables nombre, cedula y tipoEmpleado se declaran con el modificador de acceso private, lo cual indica que estas variables solo se pueden acceder por los métodos de la clase, este es el ocultamiento de información • Cuando un programa crea un objeto de la clase Empleado, tales variables se encapsulan en el objeto y se pueden utilizar solo mediante métodos de la clase de ese objeto. (Esto se hace a través de los métodos public de la clase) •Para que puede servir un método private? Encapsulamiento • Para que puede servir un método private? •Se conocen como métodos ayudantes, son utilizados por otros métodos de la clase pero no por instancias Encapsulamiento • El conjunto de métodos public declarados en una clase, representan la manera como otras clases se puede relacionar. Este conjunto se conoce como interfaz public • Contrario a la interfaz pública de la clase se tienen los métodos private, que se relacionan con detalles de implementación que no deben ser “vistos” o accedidos por instancias de la clase Encapsulamiento • Acceso directo a los miembros públicos de una clase Empleado1 – UsoEmpleado1 Encapsulamiento • Un atributo público se podría acceder de manera directa desde una instancia. •Sin embargo, un atributo con acceso private no! Encapsulamiento • Niveles de acceso Especificador clase subclase private X public X X paquete X Encapsulamiento • Referencias a los miembros del objeto actual mediante this Empleado3 – UsoEmpleado3 public class Empleado3 { private String nombre; private String cedula; private int tipoEmpleado; public void setNombre(String nombre) { } public void setCedula(String cedula) { } public int getTipoEmpleado() { return tipoEmpleado; } } public class Empleado3 { private String nombre; private String cedula; private int tipoEmpleado; public void setNombre(String nombre) { Establecer como nombre, el valor pasado como argumento } public void setCedula(String cedula) { } public int getTipoEmpleado() { return tipoEmpleado; } } public class Empleado3 { private String nombre; private String cedula; private int tipoEmpleado; public void setNombre(String nombre) { nombre=nombre; } public void setCedula(String cedula) { } public int getTipoEmpleado() { return tipoEmpleado; } } Qué valor se asigna a nombre? public class Empleado4 { private String nombre; private String cedula; private int tipoEmpleado; public void setNombre(String nombre) { this.nombre=nombre; } public void setCedula(String cedula) { this.cedula=cedula; } public int getTipoEmpleado() { return tipoEmpleado; } } La palabra clave this permite hacer referencia a los atributos de la clase Encapsulamiento Empleado4 – UsoEmpleado4 Encapsulamiento Miembros de clase estáticos • Cuando se crea cada objeto, éste contiene una copia de todas las variables de la clase • Existen casos en los que solo se debe compartir una copia de cierta variable entre TODOS los objetos de una clase Encapsulamiento Empleado -String primerNombre -String apellidoPaterno -cuenta Empleado(String n, String a) obtenerPrimerNombre() obtenerApellidoPaterno() obtenerCuenta() Encapsulamiento Empleado -String primerNombre -String apellidoPaterno -cuenta Empleado(String n, String a) obtenerPrimerNombre() obtenerApellidoPaterno() obtenerCuenta() cuenta indica la cantidad de empleados que se han creado hasta el momento en la ejecución de un programa Encapsulamiento e1 Oscar Bedoya 1 Empleado(String n, String a) obtenerPrimerNombre() obtenerApellidoPaterno() obtenerCuenta() Encapsulamiento e2 Sarah Meyer 2 Empleado(String n, String a) obtenerPrimerNombre() obtenerApellidoPaterno() obtenerCuenta() Encapsulamiento e1 e2 Oscar Bedoya 2 Sarah Meyer 2 Empleado(String n, String a) obtenerPrimerNombre() obtenerApellidoPaterno() obtenerCuenta() Empleado(String n, String a) obtenerPrimerNombre() obtenerApellidoPaterno() obtenerCuenta() Encapsulamiento e1 e2 Oscar Bedoya 1 Sarah Meyer 2 Empleado(String n, String a) obtenerPrimerNombre() obtenerApellidoPaterno() obtenerCuenta() Empleado(String n, String a) obtenerPrimerNombre() obtenerApellidoPaterno() obtenerCuenta() Si después de crear e2, si se utiliza la instrucción e1.obtenerCuenta(), que valor se mostrará? Encapsulamiento e1 e2 Oscar Bedoya 1 Sarah Meyer 2 Empleado(String n, String a) obtenerPrimerNombre() obtenerApellidoPaterno() obtenerCuenta() Empleado(String n, String a) obtenerPrimerNombre() obtenerApellidoPaterno() obtenerCuenta() El atributo cuenta siempre tiene el mismo valor para todos los objetos de la clase (en un tiempo dado). Se comparte el atributo entre TODOS los objetos de la clase Encapsulamiento Miembros de clase estáticos • Para lograr que un atributo se comparta entre todas las instancias creadas de una clase, se debe declarar como static public class Empleado5{ private String primerNombre; private String apellidoPaterno; private static int cuenta = 0; } Se declara el atributo cuenta como static public class Empleado5{ private String primerNombre; private String apellidoPaterno; private static int cuenta = 0; En qué momento se debe aumentar el valor de cuenta } public class Empleado5{ private String primerNombre; private String apellidoPaterno; private static int cuenta = 0; public Empleado5( String nombre, String apellido ){ primerNombre = nombre; apellidoPaterno = apellido; cuenta++; } } public class Empleado5{ private String primerNombre; private String apellidoPaterno; private static int cuenta = 0; public Empleado5( String nombre, String apellido ){ primerNombre = nombre; apellidoPaterno = apellido; cuenta++; } public String obtenerPrimerNombre() { return primerNombre; } public static int obtenerCuenta() { return cuenta; } } Método static import javax.swing.*; public class PruebaEmpleado5{ public static void main( String args[] ) { Empleado5 e1 = new Empleado5( "Maria", "Flores" ); System.out.println(“Cuenta= “ + e1.obtenerCuenta() ); Empleado5 e2 = new Empleado5( "Juan", "Perez" ); System.out.println(“Cuenta= “ + e1.obtenerCuenta() ); System.out.println(“Cuenta= “ + e2.obtenerCuenta() ); System.out.println(“Cuenta= “ + Empleado5.obtenerCuenta() ); System.exit( 0 ); } } import javax.swing.*; public class PruebaEmpleado5{ public static void main( String args[] ) { Empleado5 e1 = new Empleado5( "Maria", "Flores" ); System.out.println(“Cuenta= “ + e1.obtenerCuenta() ); Empleado5 e2 = new Empleado5( "Juan", "Perez" ); System.out.println(“Cuenta= “ + e1.obtenerCuenta() ); System.out.println(“Cuenta= “ + e2.obtenerCuenta() ); System.out.println(“Cuenta= “ + Empleado5.obtenerCuenta() ); System.exit( 0 ); } } En este punto cuenta es 1 import javax.swing.*; public class PruebaEmpleado5{ public static void main( String args[] ) { Empleado5 e1 = new Empleado5( "Maria", "Flores" ); System.out.println(“Cuenta= “ + e1.obtenerCuenta() ); Empleado5 e2 = new Empleado5( "Juan", "Perez" ); System.out.println(“Cuenta= “ + e1.obtenerCuenta() ); System.out.println(“Cuenta= “ + e2.obtenerCuenta() ); System.out.println(“Cuenta= “ + Empleado5.obtenerCuenta() ); System.exit( 0 ); } } En este punto cuenta es 2 import javax.swing.*; public class PruebaEmpleado5{ public static void main( String args[] ) { Empleado5 e1 = new Empleado5( "Maria", "Flores" ); System.out.println(“Cuenta= “ + e1.obtenerCuenta() ); Empleado5 e2 = new Empleado5( "Juan", "Perez" ); System.out.println(“Cuenta= “ + e1.obtenerCuenta() ); System.out.println(“Cuenta= “ + e2.obtenerCuenta() ); System.out.println(“Cuenta= “ + Empleado5.obtenerCuenta() ); System.exit( 0 ); } } En este punto cuenta es 2 import javax.swing.*; public class PruebaEmpleado5{ public static void main( String args[] ) { Empleado5 e1 = new Empleado5( "Maria", "Flores" ); System.out.println(“Cuenta= “ + e1.obtenerCuenta() ); Empleado5 e2 = new Empleado5( "Juan", "Perez" ); System.out.println(“Cuenta= “ + e1.obtenerCuenta() ); System.out.println(“Cuenta= “ + e2.obtenerCuenta() ); System.out.println(“Cuenta= “ + Empleado5.obtenerCuenta() ); System.exit( 0 ); } } Se puede utilizar el nombre de la clase para conocer el valor de cuenta Siempre y cuando el método sea static import javax.swing.*; public class PruebaEmpleado5{ public static void main( String args[] ) { Empleado5 e1 = new Empleado5( "Maria", "Flores" ); System.out.println(“Cuenta= “ + e1.obtenerCuenta() ); Empleado5 e2 = new Empleado5( "Juan", "Perez" ); System.out.println(“Cuenta= “ + e1.obtenerCuenta() ); System.out.println(“Cuenta= “ + e2.obtenerCuenta() ); System.out.println(“Cuenta= “ + Empleado5.obtenerCuenta() ); System.exit( 0 ); } } Empleado5 – UsoEmpleado5 Se puede utilizar el nombre de la clase para conocer el valor de cuenta Encapsulamiento Recolección de basura • Cuando se crea un objeto se asignan recursos del sistema • Suponga que en un programa se crea un objeto, procesa cierta información y no se requiere más de este objeto para continuar con el funcionamiento del programa • Se debería eliminar el objeto y así liberar los recursos que le fueron asignados Encapsulamiento Recolección de basura Si ya no se necesita un objeto, se puede eliminar explícitamente referenciándolo a null. Por ejemplo, si el objeto empleado e1 no se requiere, se puede colocar: • e1=null: Encapsulamiento Recolección de basura • Java realiza automáticamente una recolección de basura (Garbage collector) para ayudar a regresar al sistema la memoria ocupada por los objetos que ya no se utilizan •Cuando ya no existen más referencias a un objeto, éste queda marcado para la recolección de basura •La memoria que fue asignada a ese objeto se recupera cuando se ejecute el recolector de basura Encapsulamiento Recolección de basura • Para ejecutar el recolector de basura se utiliza la instrucción: System.gc(); import javax.swing.*; public class PruebaEmpleado5{ public static void main( String args[] ) { Empleado5 e1 = new Empleado5( "Maria", "Flores" ); e1=null; System.gc(); Empleado5 e2 = new Empleado5( "Juan", "Perez" ); System.exit( 0 ); } } import javax.swing.*; public class PruebaEmpleado5{ public static void main( String args[] ) { Empleado5 e1 = new Empleado5( "Maria", "Flores" ); e1=null; System.gc(); Empleado5 e2 = new Empleado5( "Juan", "Perez" ); System.exit( 0 ); } } Se referencia el objeto e1 a null import javax.swing.*; public class PruebaEmpleado5{ public static void main( String args[] ) { Empleado5 e1 = new Empleado5( "Maria", "Flores" ); e1=null; System.gc(); Empleado5 e2 = new Empleado5( "Juan", "Perez" ); System.exit( 0 ); } } Se ejecuta el recolector de basura Encapsulamiento Recolección de basura • Cuando utilice el recolector de basura y esté al mismo tiempo empleando atributos static para compartir su valor a través de objetos debe tener ciertos cuidados import javax.swing.*; public class PruebaEmpleado5{ public static void main( String args[] ) { Empleado5 e1 = new Empleado5( "Maria", "Flores" ); System.out.println(“Cuenta= “ + e1.obtenerCuenta() ); e1=null; System.gc(); Empleado5 e2 = new Empleado5( "Juan", "Perez" ); System.out.println(“Cuenta= “ + e2.obtenerCuenta() ); System.out.println(“Cuenta= “ + Empleado5.obtenerCuenta() ); System.exit( 0 ); } } Qué valor se muestra? Qué valor se debería mostrar? import javax.swing.*; public class PruebaEmpleado5{ public static void main( String args[] ) { Empleado5 e1 = new Empleado5( "Maria", "Flores" ); System.out.println(“Cuenta= “ + e1.obtenerCuenta() ); e1=null; System.gc(); Empleado5 e2 = new Empleado5( "Juan", "Perez" ); Cuando el recolector de basura elimine el objeto, se debería disminuir cuenta en 1 System.out.println(“Cuenta= “ + e2.obtenerCuenta() ); System.out.println(“Cuenta= “ + Empleado5.obtenerCuenta() ); System.exit( 0 ); } } Encapsulamiento Recolección de basura • Toda clase en Java cuenta con un método finalizador que regresa los recursos al sistema •El método finalizador contiene instrucciones que se deben realizar justo antes de que el recolector de basura lo elimine •La firma del método finalizador es la siguiente: protected void finalize() Encapsulamiento protected void finalize() { cuenta--; System.out.println("Finalizador de Empleado: " + primerNombre + " " + apellidoPaterno + ". Ahora cuenta vale " + cuenta ); } Se disminuye el valor de cuenta en 1 Empleado6 – UsoEmpleado6 Encapsulamiento Variables de tipo final • Algunas variables necesitan modificarse, mientras que otras no •Se utiliza la palabra final para indicar que una variable no puede modificar su valor Encapsulamiento Variables de tipo final •Se le asigna un valor solamente en uno de las dos situaciones siguientes: -Al momento de declarar la variable -En el constructor •Cualquier intento de asignar un valor en un lugar diferente a la declaración o al constructor produce un error de compilación Encapsulamiento Variables de tipo final • Para definir una variable de tipo final, se especifica en la declaración modificadorAcceso final tipo nombreVariable; Encapsulamiento Variables de tipo final • Para definir una variable de tipo final, se especifica en la declaración public final String primerNombre; Encapsulamiento public class Empleado{ public String nombre; public String cedula; public int tipoEmpleado; private final int PORCENTAJE_SALUD=8; ... } Se establece que el porcentaje de salud no se puede modificar Encapsulamiento Variables de tipo final public void actualizarPorcentaje(int nuevo) { PORCENTAJE_SALUD=nuevo; } No se pueden tener métodos que modifiquen el valor de una variable que se establece como final Empleado7 – UsoEmpleado7 Encapsulamiento Paquetes • Cuando las aplicaciones se vuelven complejas se puede llegar a tener muchas clases •Resulta más práctico para el programador agrupar un conjunto de clases en un directorio, este grupo de clases se conoce como paquete •Los paquetes también contribuyen a la reutilización de código •Un programa puede importar una o varias clases de diferentes paquetes implementados por él mismo, no siempre de paquetes predefinidos Encapsulamiento Paquetes Los pasos para la creación de paquetes son los siguientes: •Cree la clase que va a colocar en el paquete •Elija el nombre del paquete. Puede ser una secuencia de subdirectorios, por ejemplo, el nombre de paquete eisc.interactiva.clase7 indica que el paquete quedará ubicado en el directorio clase7 que se encuentra en el directorio interactiva y éste a su vez en el directorio eisc •Coloque como primer línea de la clase la instrucción: package eisc.interativa.clase7; •Compile la clase. Java creará los subdirectorios y colocará el archivo .class Encapsulamiento Paquetes Los pasos para la utilización de paquetes son los siguientes: •Importe la clase en un programa. Importar la clase por medio de la instrucción: import eisc.interativa.clase7.nombreClase; Esta línea debe ser la primera línea del programa •Utilice la clase. Tal como se ha hecho en los casos anteriores Encapsulamiento Paquetes Los pasos para la utilización de paquetes son los siguientes: •Importe la clase en un programa. Importar la clase por medio de la instrucción: import eisc.interativa.clase7.nombreClase; Esta línea debe ser la primera línea del programa •Utilice la clase. Tal como se ha hecho en los casos anteriores Estudiante – Docente - UsaClases Encapsulamiento Problema: •Cree los siguientes paquetes -Figuras2D: contiene las clases Circulo, Cuadrado y Triangulo. Los atributos de estas clases debe ser private y tener métodos public. Utilice constructores. Incluya la utilización de la palabra this. Defina una variable de tipo static que permite conocer la cantidad de objetos creados de cada clase. •Figuras3D: contiene las clases Cubo y Esfera. Siga instrucciones correspondiente para el caso •Desarrolle las clase UsoFiguras donde se importen las clases de ambos paquetes