Download CAPITULO III PROGRAMACION ORIENTADA A OBJETOS 3.1
Document related concepts
no text concepts found
Transcript
CAPITULO III PROGRAMACION ORIENTADA A OBJETOS 3.1 CONTROL DE ACCESO MODIFICADO 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. Únicamente puede ser accedido desde los métodos de la clase. Se hacen privados los atributos cuando se desea proteger los accesos. 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. Puede ser accedido desde cualquier método de otra clase. 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. Puede accesarse desde la misma clase o clases derivadas. Nota: Por lo general al momento de declarar los atributos en una clase su acceso debe ser privado (private). 3.2 MÉTODOS: DECLARACIÓN E IMPLEMENTACIÓN Los métodos son funciones que pueden ser llamadas dentro de la clase o por otras clases. La implementación de un método consta de dos partes, una declaración y un cuerpo. La declaración en Java de un método se puede expresar esquemáticamente como: Control de acceso tipoRetorno nombreMetodo( [lista_de_argumentos]){ } modificador_de_ acceso tipo_retorno nombreMetodo([lista_de_argumentos]){ public double sumar(double a, double b){ } Definición de Métodos El concepto de método consiste en una forma de encapsular un conjunto de instrucciones dentro de una declaración especifica (llamada generalmente SUBPROGRAMA), permitiendo la descomposición funcional y la diferenciación de tareas. La declaración de un método esta formada por una cabecera y un cuerpo. Estructuración en Java. La codificación de un método consiste en una cabecera para su identificación y de un cuerpo que contiene las sentencias que este ejecuta. La cabecera se compone de un nombre (identificador del método), el tipo del resultado (tipos primitivos o clases) y una lista de parámetros, que puede contener cero o más variables. La lista de parámetros consiste en cero o mas parámetros formales (variables), cada uno de ellos con un tipo. En caso que el método tenga más de un parámetro, estos deben ir separados con una coma. Firma de métodos, nombre + numero de argumentos. Llamada a un método. Los métodos pueden ser invocados o llamados de cualquier método de la clase, incluido al mismo. Además, cuando se invoca, hay que pasar un valor a cada parámetro, a través de una variable o un valor constante. En Java, la acción de pasar valores a parámetros de tipo primitivo (int, double, boolean, char..) se denomina paso de parámetros por valor package org.javaboys.bank.modelo; public class CuentaBancaria { private int numero; private double balance; private Persona propietario; public void debitar(double monto){ balance-=monto; } public void acreditar(double monto){ balance+=monto; } } 3.3 METODOS CON NÚMERO DE PARÁMETROS VARIABLE Ejemplos: public class ParametrosVariable { public double sumar(double a, double b) { double total = 0.0; return total; } public double sumar(double...numeros){ double t=0.0; for(double n:numeros){ t=t+n; } return t; } } 3.4 AMBITOS DE VARIABLES El ámbito de una aplicación. Este puede ser: Local: Cuando la misma sólo es accesible desde un único procedimiento hijo, no pudiendo ser leída o modificada desde otro procedimiento hermano o desde el propio procedimiento padre. Es posible declarar variables en bloques de condición, bucles, etc. de tal modo que sólo pueda accederse a ellas en el propio bloque. Global: Cuando la misma es accesible tanto desde rutinas o macros de la aplicación, como en todos los procedimientos y funciones de la misma. Si bien es cierto, que de una forma básica, se puede definir el ámbito de las variables de la forma expuesta más arriba, existen grados de globalidad de las mismas, pudiendo ser accesibles desde unos puntos u otros, o incluso pudiendo ser accesibles entre aplicaciones distintas, llegando al caso de la superglobalidad. Ejemplo del ámbito de una variable en el lenguaje de programación Java. public class A { public Integer numeroEntero = new Integer(); /* Variable Global a todos los Métodos */ public Integer metodo() { int num = 1; // Variable Local a método. Puede accederse dentro de este método en cualquier parte, pero no fuera del mismo. for (int i = 0;i<numeroEntero.intValue();i++) { // i es local al bucle for, sólo puede ser accedida dentro del mismo. num *= i; } // i = 2; Esta línea provocaría error al no haber declarado la variable i. i fue definida localmente al bucle for. return Integer.valueOf(num); } public void otroMetodo() { int num = 1; // Variable local a otroMetodo. num aquí es una variable distinta a la variable num de método System.out.println("Variable local num: " + num); } } Hay que tener en cuenta que en Java el caso de las variables globales a todos los métodos que se encuentran en una clase, es algo peculiar, ya que estas realmente son atributos que definen un objeto de una clase determinada, en este caso la clase A tiene un atributo llamado numeroEntero. El atributo es un concepto que define a un objeto de una clase determinada, mientras que una variable sirve de apoyo a los procedimientos y no define conceptualmente objetos. Los bloques de sentencias compuestas en Java se delimitan con dos llaves. Las variables de Java solo son validas desde el punto donde están declaradas hasta el final de la sentencia compuesta que la engloba. Se pueden anidar estas sentencias compuestas, y cada una puede contener su propio conjunto de declaraciones de variables locales. Sin embargo, no se puede declarar una variable con el mismo nombre que una de ámbito exterior. 3.5 CONSTRUCTORES Método que establece una nueva instancia de una clase. Una clase contiene mínimo un constructor. Se usan para crear e inicializar objetos . Siempre tienen el mismo nombre de la clase. No tienen tipo de retorno: No retornan valores. Pero cuando se usan con new retornan una referencia al nuevo objeto. El constructor es un tipo específico de método que siempre tiene el mismo nombre que la clase y se utiliza para construir objetos de esa clase. No tiene tipo de dato específico de retorno, ni siquiera void. Esto se debe a que el tipo específico que debe devolver un constructor de clase es el propio tipo de la clase. En este caso, pues, no se puede especificar un tipo de retorno, ni se puede colocar ninguna sentencia que devuelva un valor. Los constructores pueden sobrecargarse, y aunque puedan contener código, su función primordial es inicializar el nuevo objeto que se instancia de la clase. En Java, ha de hacerse una llamada explícita al constructor para instanciar un nuevo objeto. Cuando se declara una clase en Java, se pueden declarar uno o más constructores opcionales que realizan la inicialización cuando se instancia (se crea una ocurrencia) un objeto de dicha clase. Sobrecarga De Constructores Sobrecarga: Cuando existe más de un constructor con diferentes parámetros. Los constructores son comúnmente sobrecargados para permitir diferentes formas de crear e inicializar instancias (objetos). Constructores Por Defecto El constructor por defecto no tiene parámetros. Java provee uno sólo si no se define explícitamente un constructor. Cuando escribimos un constructor personalizado, el constructor por defecto desaparece. Entonces si se quiere recuperarlo hay que codificarlo. public class Cuenta { //Constantes public static final double LIMITE_NORMAL=300.; //Variables de instancia private double balance=.0; private double limit= LIMITE_NORMAL; //Métodos ... } Al crear un objeto de tipo Cuenta con new Cuenta(), se llama al constructor por defecto de la clase Cuenta, con lo cual se crea un objeto de tipo Cuenta cuyo estado inicial será indicado en la inicialización de las variables de instancia balance y limit. Constructores definidos por el usuario Los lenguajes de programación nos permiten definir constructores para especificar como a de inicializarse un objeto al crearlo. El nombre del constructor ha de coincidir con el nombre de la clase Podemos definir un constructor para inicializar las variables de instancia de una clase, en vez de hacerlo en la propia declaración de las variables de instancia: public class Cuenta { //Constantes public static final double LIMITE_NORMAL=300.; //Variables de instancia private double balance=.0; private double limit; //Constructor sin parámetros public Cuenta(){ this.balance=.0; this.limit=LIMITE_NORMAL; } //Métodos ... } La palabra reservada this hace referencia al objeto que realiza la operación cuya implementación especifica el método. Uso de ‘this’ en constructores: this (argumentos) En un constructor la palabra reservada this es usada para referirse a otro constructor en la misma clase: De estar en la primera línea del constructor. Se denomina encadenamiento de constructores. 3.6 USO DE OBJETOS El operador (.) El operador. (Punto) en java nos permite acceder a los distintos miembros de una clase: objeto.miembro Cuando tenemos un objeto de un tipo determinado y queremos acceder a uno de sus miembros solo tenemos que poner el identificador asociado al objeto(esto es, el identificador de una de las variables de nuestro programa) seguido por un punto y por el identificador que hace referencia a un miembro concreto de la clase a la que pertenece el objeto. ¿Cómo se comprueba el estado de un objeto? Accediendo a las variables de instancia del objeto objeto.atributo Por ejemplo, cuenta.balance nos permitirá acceder al valor numérico correspondiente al saldo de una cuenta, siempre y cuando cuenta fuese una instancia de la clase Cuenta. ¿Cómo se le envía un mensaje a un objeto? Invocando a uno de sus métodos. objeto.metodo(lista de parámetros) La llamada al método hace que el objeto realice la tarea especificada en la implementación del método, tal como esté definida en la definición de la clase que pertenece el objeto. Ejemplos: cuenta.ingresar(150.00) Si cuenta es el identificador asociado a una variable de tipo Cuenta, se invoca al método ingresar definido en la clase Cuenta para depositar una cantidad de dinero en la cuenta. La implementación del método ingresar se encarga de actualizar el saldo de la cuenta, sin que nosotros nos tengamos que preocupar de cómo se realiza esta operación. System.out.println(“mensaje”); System es el nombre de una clase incluida en la biblioteca de clases estándar de Java. System.out es un miembro de la clase System que hace referencia al objeto que representa la salida estándar de una aplicación Java. println() es un método definido en la clase a la que pertenece el objeto System.out. La implementación del método println() se encarga de mostrar el mensaje que le pasamos como parámetro y hace avanzar el curso hasta la siguiente línea (como si pulsásemos la tecla enter). System.out.println() es una llamada a un método, el método println() del objeto System.out. La línea completa forma una sentencia (terminada con un punto y coma) que delega en el método println() para que este se encargue de mostrar una línea en pantalla. Creación de objetos Antes de poder usar un objeto hemos de crearlo… El operador new El operador new nos permite crear objetos en Java. Tipo identificador = new Tipo(); Si escribimos un programa como el siguiente : public class Ingreso { public static void main(String[] args) { Cuenta cuenta; //Error cuenta.ingresar(100.00); } } El compilador nos da el siguiente error: Ingreso.java:7: variable cuenta might not have been initialized cuenta.ingresar(100.00); Hemos declarado una variable que, inicialmente, no tiene ningún valor. Antes de utilizarla, deberíamos haberla inicializado(con un objeto del tipo adecuado): Cuenta cuenta = new Cuenta(); Observaciones Se suele crear una clase aparte, que únicamente contenga un método main, como punto de entrada de la aplicación. En la implementación del método main se crean los objetos que sean necesarios y se les envían mensajes para indicarles lo que deseamos que hagan. Allan Kay, describió las 5 principales características de Smalltalk, uno de los primeros lenguajes orientados a objetos y uno de los lenguajes en los cuales esta basado Java: Todo es un objeto: Considere un objeto una variable especial, no solamente guarda datos, sino también se pueden hacer solicitudes a este Objeto en sí. En teoría, cualquier elemento en el problema espacial(real) (edificios, servicios, automóviles, u otra entidad) puede ser representado como un objeto en un programa. Un programa es un conjunto de Objetos, enviándose mensajes entre sí : Para realizar una solicitud a un Objeto es necesario enviarle un mensaje. Concretamente se puede pensar que un mensaje es una solicitud para llamar una función que pertenece a cierto objeto. Cada Objeto tiene su memoria, conformada por otros Objetos : En otras palabras, es posible generar un tipo de Objeto nuevo agrupando Objetos existentes. De esta manera se pueden armar estructuras complejas en un programa, escondidas detrás de la simplicidad de Objetos. Todo Objeto tiene su Tipo: En este sentido Tipo se refiere a Clase, donde cada Objeto es una instancia de una Clase en cuestión. La característica más importante de una Clase es el tipo de mensajes que pueden ser enviados a ella. Todo Objeto de un mismo tipo puede recibir los mismos mensajes : Esto implica que si un Objeto es del tipo Circulo, un Objeto del tipo Figura será capaz de recibir mensajes de Circulo, puesto que un Circulo es una figura. Este concepto forma parte medular de todo lenguaje orientado a Objetos y será explorado en una sección específica de este curso. 3.7 SOBRECARGA DE METODOS Consiste en crear varios métodos con el mismo nombre pero con diferentes firmas: overloading. Es decir en una misma clase pueden existir dos métodos con el mismo nombre pero con diferentes parámetros. Ejemplo, el método println del objeto out perteneciente a la clase System tiene 10 declaraciones con diferentes parámetros : boolean, char[], char, double, float, int, long, Object, String. La sobrecarga de métodos es justo lo mismo; creamos varios métodos con el mismo nombre que actúen diferente según el tipo de los parámetros de entrada. Por ejemplo, queremos hacer un método que devuelva el resultado de la suma de los dos parámetros de entrada, pero no sabemos si será un entero o si tendrá decimales, así que tendremos que hacer un método para el caso de los decimales, y otro con el mismo nombre para el caso de los enteros La sobrecarga de métodos Es la creación de varios métodos con el mismo nombre pero con diferentes firmas y definiciones. yaba utiliza el número y tipo de argumentos para seleccionar cuál definición de método ejecutar. Java diferencia los métodos sobrecargados con base en el número y tipo de argumentos que tiene el método y no por el tipo que devuelve. A la hora de llamar a un método sobrecargado, Java sigue unas reglas para determinar el método concreto que debe llamar: Si existe el método cuyos argumentos se ajustan exactamente al tipo de los argumentos de la llamada (argumentos actuales), se llama ese método. Si no existe un método que se ajuste exactamente, se intenta promover los argumentos actuales al tipo inmediatamente superior (por ejemplo char a int, int a long, float a double, etc.) y se llama el método correspondiente. Si sólo existen métodos con argumentos de un tipo más amplio (por ejemplo, long en vez de int), el programador debe hacer un cast explícito en la llamada, responsabilizándose de esta manera de lo que pueda ocurrir. El valor de retorno no influye en la elección del método sobrecargado. En realidad es imposible saber desde el propio método lo que se va a hacer con él. No es posible crear dos métodos sobrecargados, es decir con el mismo nombre, que sólo difieran en el valor de retorno. Diferente de la sobrecarga de métodos es la redefinición. Una clase puede redefinir(override) un método heredado de una superclase. Redefinir un método es dar una nueva definición. 3.8 PAQUETES Son unidades de agrupamiento de clases, pueden ser agrupados o clasificadas acuerdo al contexto. Por convención se usan los nombres de dominios de internet: .com, .net, .org, .gov, etc. Diferentes paquetes pueden contener clases con el mismo nombre. Al compilarse los paquetes se generan una estructura jerárquica de directorios de acuerdo a los nombres separados por”.” Para explicar el tema de los paquetes imaginarse una ciudad en la cual hay varios bloques de apartamentos propiedad de una única empresa inmobiliaria. Esta empresa dispone además de comercios, zonas de recreo y almacenes. Se puede pensar en la empresa como una lista de referencias a cada una de sus propiedades; es decir, la inmobiliaria sabe exactamente donde está un apartamento determinado y puede hacer uso de él en el momento en que lo necesite. Si ahora se mira lo anterior en términos de Java, la empresa inmobiliaria es el paquete. Los paquetes agrupan a librerías de clases, como las librerías que contienen información sobre distintas propiedades comerciales. Un paquete será, pues, la mayor unidad lógica de objetos en Java. Declaración de Paquetes Los paquetes se declaran utilizando la palabra package seguida del nombre del paquete. Esto debe estar al comienzo del fichero fuente, en concreto, debe ser la primera sentencia ejecutable del código Java, excluyendo, claro está, los comentarios y espacios en blanco. Por ejemplo: package mamiferos; class Ballena { ... } En este ejemplo, el nombre del paquete es mamiferos. La clase Ballena se considera como parte del paquete. La inclusión de nuevas clases en el paquete es muy sencilla, ya que basta con colocar la misma sentencia al comienzo de los ficheros que contengan la declaración de las clases. A la hora de crear un paquete hay que tener presente una serie de ideas: La palabra clave package debe ser la primera sentencia que aparezca en el fichero, exceptuando, claro está, los espacios en blanco y comentarios Es aconsejable que todas las clases que vayan a ser incluidas en el paquete se encuentren en el mismo directorio. Como se ha visto, esta recomendación se la puede uno saltar a la torera, pero se corre el riesgo de que aparezcan determinados problemas difíciles de resolver a la hora de compilar, en el supuesto caso de que no se hile muy fino Ante todo, recordar que en un fichero únicamente puede existir, como máximo, una clase con el especificador de acceso public, debiendo coincidir el nombre del fichero con el nombre de la clase