Centro Asociado Palma de Mallorca Tutor: Antonio Rivero Cuesta

Capítulo 1 Objetos y Clases Centro Asociado Palma de Mallorca Tutor: Antonio Rivero Cuesta 1 1 Objetos y Clases 1.1 Objetos y Clases Clase: Una cl

11 downloads 83 Views 2MB Size

Story Transcript

Capítulo 1 Objetos y Clases

Centro Asociado Palma de Mallorca Tutor: Antonio Rivero Cuesta 1

1 Objetos y Clases 1.1 Objetos y Clases Clase: Una clase es una plantilla donde vamos a definir unos atributos y unos métodos. Una clase es la implementación de un tipo de objeto, considerando los objetos como instancias de las clases. Objeto: Cuando se crea un objeto, se instancia una clase, mediante el operador new. Se ha de especificar de qué clase es el objeto instanciado, para que el compilador comprenda las características del objeto.

1.2 Creación de Objetos Cuando se instancia un objeto el compilador crea en la memoria dinámica un espacio para tantas variables como atributos tenga la clase a la que pertenece el objeto.

1.3 Invocación de métodos Podemos comunicarnos con los objetos invocando sus métodos. Generalmente, los objetos hacen algo cuando invocamos un método.

1.4 Parámetros Los métodos pueden tener parámetros para aportar información adicional para realizar una tarea. El encabezado de un método se denomina signatura, proporciona la información necesaria para invocar dicho método. Los métodos pueden tener cualquier número de parámetro.

1.5 Tipos de dato Los parámetros tienen tipos. El tipo define la clase de valor que un parámetro puede tomar.

1.6 Instancias múltiples Se pueden crear muchos objetos similares a partir de una sola clase. Cada uno de los atributos del objeto tendrá sus propios valores.

1.7 Estado Los objetos tienen un estado. El estado está representado por todos los valores almacenados en los campos o atributos.

1.8 ¿Qué es lo que contiene un objeto? Cuando se crea un objeto, se instancia una clase, mediante el operador new. Todos los objetos de la misma clase tienen los mismos campos. Los valores concretos de cada campo particular de cada objeto pueden ser diferentes. Los métodos se definen en la clase del objeto. Todos los objetos de la misma clase tienen los mismos métodos.

2

1.9 Código Java Cuando programamos en Java, escribimos instrucciones para invocar métodos sobre objetos. Tenemos que escribir los comandos correspondientes de forma textual. Cuando creamos un objeto, lo que hacemos es almacenar ese objeto en una variable. Para llamar a un método, escribimos el nombre del objeto seguido de punto y seguido del nombre del método, terminamos con una lista de parámetros o con un par de paréntesis vacíos si no hay parámetros. Todas las instrucciones Java terminan con un punto y coma.

1.10 Interacción entre Objetos Lo normal es crear una clase principal que inicie el resto.

1.11 Código Fuente Cada clase tiene algún código fuente asociado. El código fuente es un texto que define los detalles de la clase. El código fuente es un texto escrito en lenguaje de programación Java y define qué campos y métodos tiene la clase y qué ocurre cuando se invoca un método. El arte de la programación, que no es tarea fácil, consiste en aprender cómo escribir estas definiciones de clases. Cuando realiza algún cambio en el código, la clase necesita ser compilada haciendo clic en el botón Compile. Una vez que una clase ha sido compilada, se pueden crear nuevamente objetos y probar sus cambios.

1.13 Valores de retorno Los métodos que devuelven o retornan valores nos permiten obtener información sobre un objeto mediante una llamada al método. Quiere decir que podemos usar métodos tanto para cambiar el estado de un objeto como para investigar su estado. Con la palabra void indicamos que ese método no retoma ningún resultado.

1.14 Objetos como parámetros Los objetos pueden ser pasados como parámetros a los métodos de otros objetos. En el caso de que un método espere un objeto como parámetro, el nombre de la clase del objeto que espera se especifica como el tipo de parámetro en la signatura de dicho método.

3



Objetos y Clases ............................................................................................................................... 2  1.1 

Objetos y Clases ........................................................................................................................ 2 

1.2 

Creación de Objetos ................................................................................................................... 2 

1.3 

Invocación de métodos .............................................................................................................. 2 

1.4 

Parámetros ................................................................................................................................. 2 

1.5 

Tipos de dato.............................................................................................................................. 2 

1.6 

Instancias múltiples ................................................................................................................... 2 

1.7 

Estado ........................................................................................................................................ 2 

1.8 

¿Qué es lo que contiene un objeto? ........................................................................................... 2 

1.9 

Código Java ............................................................................................................................... 3 

1.10  Interacción entre Objetos ........................................................................................................... 3  1.11  Código Fuente ............................................................................................................................ 3  1.13  Valores de retorno...................................................................................................................... 3  1.14  Objetos como parámetros .......................................................................................................... 3 

4

Capítulo 2 De fin ici ones de Clases

Centro Asociado Palma de Mallorca Tutor: Antonio Rivero Cuesta 1

2 Definiciones de Clases 2.3 La cabecera de la clase El código de las clases puede dividirse en dos partes principales: un envoltorio exterior que simplemente da nombre a la clase y una parte interna mucho más grande que hace todo el trabajo. El envoltorio exterior tiene la siguiente apariencia: public class { } El envoltorio exterior de las diferentes clases es muy parecida, su principal finalidad es proporcionar un nombre a la clase. Por convenio, los nombres de las clases comienzan siempre con una letra mayúscula.

2.3.1 Palabras clave o reservadas Las palabras reservadas son identificadores predefinidos que tienen un significado para el compilador y por tanto no pueden usarse como identificadores creados por el usuario en los programas. Las palabras reservadas en Java ordenadas alfabéticamente son las siguientes: abstract assert boolean break byte case catch char class const

continue default do double else enum extends final finally float

for goto if implements import instanceof int interface long native

new package private protected public return short static strictfp super

switch synchronized this throw throws transient try void volatile while

2.4 Campos, constructores y métodos La parte interna de la clase es el lugar en el que definimos los campos, constructores y métodos que dan a los objetos de la clase sus características particulares y su comportamiento. Podemos resumir las características esenciales de estos tres componentes de una clase como sigue:  Los campos almacenan datos para que cada objeto los use.  Los constructores permiten que cada objeto se prepare adecuadamente cuando es creado.  Los métodos implementan el comportamiento de los objetos. En Java existen muy pocas reglas sobre el orden que se puede elegir para definir los campos, los constructores y los métodos dentro de una clase. Es importante elegir un estilo y luego usarlo de manera consistente, porque de este modo las clases serán más fáciles de leer y de comprender.

2

Orden de campos, constructores y métodos: public class NombreDeClase { Campos Constructores Métodos }

2.4.1 Campos Los campos almacenan datos de manera persistente dentro de un objeto y son accesibles para todos los métodos del objeto. Los campos también son conocidos como variables de instancia. Como los campos pueden almacenar valores que pueden variar a lo largo del tiempo, podemos llamarlos variables. Los campos son pequeñas cantidades de espacio dentro de un objeto que pueden usarse para almacenar datos de manera persistente. Todos los objetos una vez creados dispondrán de un espacio para cada campo declarado en su clase. Las variables de clase, también se conocen como variables estáticas, siempre tienen el mismo valor para todos los objetos de una determinada clase. En realidad no son variables sino constantes Los comentarios se insertan en el código de una clase para proporcionar explicaciones a los lectores humanos. No tienen ningún efecto sobre la funcionalidad de la clase. Los comentarios de una sola línea van precedidos de los caracteres “//”. Los comentarios más detallados, que frecuentemente ocupan varias líneas, se escriben generalmente en la forma de comentarios multilínea: comienzan con el par de caracteres “/*” y terminan con el par “*/”. Para definir una variable de campo dentro de una clase seguiremos el siguiente patrón:  Normalmente, comienzan con la palabra clave private.  Incluyen un nombre de tipo, int, String, etc.  Incluyen un nombre elegido por el usuario para la variable de campo.  Terminan en punto y coma. El tipo de un campo especifica la naturaleza del valor que puede almacenarse en dicho campo. Si el tipo es una clase, el campo puede contener objetos de esa clase.

2.4.2 Constructores Los constructores permiten que cada objeto sea preparado adecuadamente cuando es creado. Esta operación se denomina inicialización. El constructor inicializa el objeto en un estado razonable. Uno de los rasgos distintivos de los constructores es que tienen el mismo nombre que la clase en la que son definidos. El nombre del constructor sigue inmediatamente a la palabra public. Los campos del objeto se inicializan en el constructor, bien con valores fijos, o bien con parámetros del propio constructor. En Java todos los campos son inicializados automáticamente con un valor por defecto, si es que no están inicializados explícitamente.

3

El valor por defecto para los campos enteros es 0. Sin embargo, es preferible escribir explícitamente las asignaciones. No hay ninguna desventaja en hacer esto y sirve para documentar lo que está ocurriendo realmente.

2.5 Parámetros: recepción de datos La manera en que los constructores y los métodos reciben valores es mediante sus Parámetros. Los parámetros son otro tipo de variable, igual que los campos, por lo que se utilizan para almacenar datos. Los parámetros se definen en el encabezado de un constructor o un método. Los parámetros transportan datos que tienen su origen fuera del constructor o método y hacen que esos datos estén disponibles en el interior del constructor o método. Puesto que permiten almacenar valores, los parámetros formales constituyen otra clase de variables. Distinguimos entre nombres de los parámetros dentro de un constructor o un método y valores de los parámetros fuera de un constructor o un método. Hacemos referencia a los nombres como parámetros formales y a los valores como parámetros reales. Un parámetro formal está disponible para un objeto sólo dentro del cuerpo del constructor o del método que lo declara. Decimos que el alcance de un parámetro está restringido al cuerpo del constructor o del método en el que es declarado. El tiempo de vida de un parámetro se limita a una sola llamada de un constructor o método. Cuando se invoca un constructor o método, se crea el espacio adicional para las variables de parámetro y los valores externos se copia en dicho espacio. Una vez que completó su tarea, los parámetros formales desaparecen y se pierden los valores que contienen. Por el contrario, el tiempo de vida de un campo es el mismo tiempo de vida que el del objeto al que pertenece.

2.5.1 Elección de los nombres de variable Es conveniente elegir nombres que proporcionen algo de información al lector.

2.6 Asignación Destacamos la necesidad de almacenar el valor de corta vida de un parámetro dentro de algún lugar más permanente, una variable de campo. Las sentencias de asignación almacenan el valor representado por el lado derecho de la sentencia en una variable nombrada a la izquierda. Una regla sobre las sentencias de asignación es que el tipo de una expresión debe coincidir con el tipo de la variable a la que es asignada. La misma regla se aplica también entre los parámetros formales y los parámetros reales: el tipo de una expresión de un parámetro real debe coincidir con el tipo de una variable parámetro formal.

2.7 Métodos Los métodos se componen de dos partes: una cabecera y un cuerpo. Es importante distinguir entre la cabecera del método y declaración de campos porque son muy parecidos. Podemos decir que algo es un método y no un campo porque está seguido de un par de paréntesis: «(» y «)». Obsérvese también que no hay un punto y coma al final de la signatura. 4

El cuerpo del método es la parte restante del método, que aparece a continuación de la cabecera. Está siempre encerrado entre llaves: «{« y »}». Los cuerpos de los métodos contienen las declaraciones y las sentencias que definen qué ocurre dentro de un objeto cuando es invocado ese método. Las declaraciones se utilizan para crear espacio adicional de variables temporales, mientras que las instrucciones describen las acciones del método. Cualquier conjunto de declaraciones y sentencias, ubicado entre un par de llaves, es conocido como un bloque. Por lo que el cuerpo de una clase y los cuerpos de todos los métodos de las clases son bloques. Existen, dos diferencias significativas entre las cabeceras de los constructores de una clase y de los demás métodos: Por un lado los constructores tienen el mismo nombre que la clase en la que están definidos, y por otro los métodos siempre tienen un tipo de retorno (aunque sea void) mientras que el constructor no tiene tipo de retorno. El tipo de retorno se escribe exactamente antes del nombre del método. Es una regla de Java que el constructor no puede tener ningún tipo de retorno. Por otro lado, tanto los constructores como los métodos pueden tener cualquier número de parámetros formales, inclusive pueden no tener ninguno. Los métodos pueden tener una sentencia return y es la responsable de devolver un valor que coincida con el tipo de retorno de la signatura del método. Cuando un método contiene una sentencia return, siempre es la última sentencia que se ejecuta del mismo porque una vez que se ejecutó esta sentencia no se ejecutarán más sentencias en el método. Los tipos de retorno y las instrucciones de retorno funcionan conjuntamente. Podemos decir que una llamada a un método es una especie de pregunta que se la hace el objeto y el valor de retorno proporcionado por el método es la respuesta que el objeto da a esa pregunta.

2.8 Métodos Selectores y Mutadores Los métodos selectores “get” devuelven información sobre el estado del objeto. Proporcionan acceso a información acerca del estado del objeto. Un método selector contiene generalmente una sentencia return para devolver información de un valor en particular. Devolver un valor significa que se pasa una cierta información internamente entre dos partes diferentes del programa. A los métodos que modifican el estado de su objeto los llamamos métodos mutadores. Los métodos mutadores cambian el estado de un objeto. La forma básica de mutador admite un único parámetro y este valor se utiliza para sobreescribir directamente lo que haya almacenado en uno de los campos del objeto. Los métodos mutadores los denominamos métodos "set". La cabecera de un método de mutador, "set", normalmente tiene tipo de retorno void y un solo parámetro formal, el nuevo valor del campo a modificar. Un tipo de retorno void significa que el método no devuelve ningún valor cuando es llamado; es significativamente diferente de todos los otros tipos de retorno. En el cuerpo de un método void, esta diferencia se refleja en el hecho de que no hay ninguna sentencia return. Los métodos mutadores siempre tienen al menos una sentencia de asignación. El sumar (o restar) una cantidad al valor de una variable es algo tan común que existe un operador de asignación compuesto, especial para hacerlo: «+=».

5

2.9 Imprimir desde Métodos El método System.out.println() imprime su parámetro en la terminal de texto. Una sentencia como System.out.println("# Línea BlueJ"); imprime literalmente la cadena que aparece entre el par de comillas dobles. Todas estas sentencias de impresión son invocaciones al método println del objeto System.out que está construido dentro del lenguaje Java. Cuando se usa el símbolo «+» entre una cadena y cualquier otra cosa, este símbolo es un operador de concatenación de cadenas (es decir, concatena o reúne cadenas para crear una nueva cadena) en lugar de ser el operador aritmético de suma. El método println se puede llamar sin contener ningún parámetro de tipo cadena. Esto está permitido y el resultado de la llamada será dejar una línea en blanco entre esta salida y cualquier otra que le siga.

2.13 Tomas de decisión: la instrucción condicional Una sentencia condicional realiza una de dos acciones posibles basándose en el resultado de una prueba. También son conocidas como sentencias if. Se evalúa el resultado de una verificación o prueba, si el resultado es verdadero entonces hacemos una cosa, de lo contrario hacemos algo diferente. Una sentencia condicional tiene la forma general descrita en el siguiente pseudo-código: if (llevar a cabo alguna prueba que dé un resultado verdadero o falso){ Si la prueba dio resultado verdadero, ejecutar estas sentencias } else{ Si el resultado dio falso, ejecutar estas sentencias }

La prueba que se usa en una sentencia condicional es un ejemplo de una expresión booleana. Las expresiones booleanas tienen sólo dos valores posibles: verdadero o falso (true o false). Se las encuentra comúnmente controlando la elección entre los dos caminos posibles de una sentencia condicional.

2.16 Variables locales Una variable local es una variable que se declara y se usa dentro de un solo método. Las declaraciones de las variables locales son muy similares a las declaraciones de los campos pero las palabras private o public nunca forman parte de ellas. Es muy común inicializar variables locales cuando se las declara. Se crean cuando se invoca un método y se destruyen cuando el método termina. Los constructores también pueden tener variables locales. Las variables locales se usan frecuentemente como lugares de almacenamiento temporal para ayudar a un método a completar su tarea. Podemos considerarlas como un almacenamiento de datos para un único método. Su alcance y tiempo de vida se limitan a los del método. Un error común es usar una variable local del mismo nombre que un campo evitará que el campo sea accedido dentro de un método. 6

2.17 Campos, parámetros y variables locales Las tres clases de variables pueden almacenar un valor acorde a su definición de tipo de dato. Los campos se definen fuera de los constructores y de los métodos. Los campos se usan para almacenar datos que persisten durante la vida del objeto, de esta manera mantienen el estado actual de un objeto. Tienen un tiempo de vida que finaliza cuando termina el objeto. El alcance de los campos es la clase: la accesibilidad de los campos se extiende a toda la clase y por este motivo pueden usarse dentro de cualquier constructor o método de clase en la que estén definidos. Como son definidos como privados (private), los campos no pueden ser accedidos desde el exterior de la clase. Los parámetros formales y las variables locales persisten solamente en el lapso durante el cual se ejecuta un constructor o un método. Su tiempo de vida es tan largo como una llamada, por lo que sus valores se pierden entre llamadas. Por este motivo, actúan como lugares de almacenamiento temporales antes que permanentes. Los parámetros formales se definen en el encabezado de un constructor o de un método. Reciben sus valores desde el exterior, se inicializan con los valores de los parámetros actuales que forman parte de la llamada al constructor o al método. Los parámetros formales tienen un alcance limitado a su definición de constructor o de método. Las variables locales se declaran dentro del cuerpo de un constructor o de un método. Pueden ser inicializadas y usadas solamente dentro del cuerpo de las definiciones de constructores o métodos. Las variables locales deben ser inicializadas antes de ser usadas en una expresión, no tienen un valor por defecto. Las variables locales tienen un alcance limitado al bloque en el que son declaradas. No son accesibles desde ningún lugar fuera de ese bloque.

7

Contenido 2 

Definiciones de Clases ..................................................................................................................... 2  2.3 

La cabecera de la clase .............................................................................................................. 2 

2.3.1  2.4 

Palabras clave o reservadas ................................................................................................ 2 

Campos, constructores y métodos ............................................................................................. 2 

2.4.1 

Campos ............................................................................................................................... 3 

2.4.2 

Constructores ...................................................................................................................... 3 

2.5 

Parámetros: recepción de datos ................................................................................................. 4 

2.5.1 

Elección de los nombres de variable .................................................................................. 4 

2.6 

Asignación ................................................................................................................................. 4 

2.7 

Métodos ..................................................................................................................................... 4 

2.8 

Métodos Selectores y Mutadores ............................................................................................... 5 

2.9 

Imprimir desde Métodos ............................................................................................................ 6 

2.13  Tomas de decisión: la instrucción condicional .......................................................................... 6  2.16  Variables locales ........................................................................................................................ 6  2.17  Campos, parámetros y variables locales .................................................................................... 7 

8

Capítulo 3 Interacción de Objetos

Centro Asociado Palma de Mallorca Tutor: Antonio Rivero Cuesta 1

3 Interacción de Objetos 3.2 Abstracción y Modularización Cuando un problema se agranda se vuelve más difícil mantener todos los detalles al mismo tiempo, aumenta la complejidad. La solución que usamos para tratar el problema de la complejidad es la abstracción. La abstracción es la habilidad de ignorar los detalles de las partes para centrar la atención en un nivel más alto de un problema. Dividimos el problema en subproblemas, luego en sub-subproblemas y así sucesivamente, hasta que los problemas resultan suficientemente fáciles de tratar. Una vez que resolvemos uno de los subproblemas no pensamos más sobre los detalles de esa parte, pero tratamos la solución hallada como un bloque de construcción para nuestro siguiente problema. Esta técnica se conoce como la técnica del divide y vencerás. La modularización es el proceso de dividir un todo en partes bien definidas que pueden ser construidas y examinadas separadamente, las cuales interactúan entre sí de maneras bien definidas. La modularización y la abstracción se complementan mutuamente. La modularización es el proceso de dividir cosas grandes (problemas) en partes más pequeñas. La abstracción es la habilidad de ignorar los detalles para concentrarse en el cuadro más grande.

3.3 Abstracción en el Software En el caso de programas complejos, para mantener una visión global del problema tratamos de identificar los componentes que podemos programar como entidades independientes, y luego intentamos utilizar esos componentes como si fueran partes simples sin tener en cuenta su complejidad interna. En programación orientada a objetos, estos componentes y subcomponentes son objetos. Las clases definen tipos. El nombre de una clase puede ser usado como el tipo de una variable. Las variables cuyo tipo es una clase pueden almacenar objetos de dicha clase. El tipo de un campo especifica la naturaleza del valor que puede almacenarse en dicho campo. Si el tipo es una clase, el campo puede contener objetos de esa clase.

3.6 Diagramas de Clases con Diagramas de Objetos El diagrama de clases muestra las clases de una aplicación y las relaciones entre ellas. Da información sobre el código. Representa la vista estática de un programa. El diagrama de objetos muestra los objetos y sus relaciones en un instante determinado de la ejecución de una aplicación. Da información sobre los objetos en tiempo de ejecución. Representa la vista dinámica de un programa.

a) diagrama de objetos;

b) diagrama de clases

2

El diagrama de objetos también muestra otro detalle importante, cuando una variable almacena un objeto, éste no es almacenado directamente en la variable sino que en la variable sólo se almacena una referencia al objeto. Referencia a un objeto. Las variables de tipo objeto almacenan referencias a los objetos.

3.7 Tipos Primitivos y Tipos Objeto Java reconoce dos clases de tipos muy diferentes: los tipos primitivos y los tipos objeto. Los tipos primitivos están todos predefinidos en el lenguaje Java Los tipos primitivos en Java son todos los tipos que no son objetos. Los tipos primitivos más comunes son los tipos int, booleano, char, double y long. Los tipos primitivos no poseen métodos. Tanto los tipos primitivos como los tipos objeto pueden ser usados como tipos, pero existen situaciones en las que se comportan de manera muy diferente. Una diferencia radica en cómo se almacenan los valores. Los valores primitivos se almacenan directamente en una variable. Por otro lado, los objetos no se almacenan directamente en una variable sino que se almacena una referencia al objeto.

3.8 El código fuente para ClockDisplay Ver código 3.3, página 71. Operadores Lógicos Los operadores lógicos operan con valores booleanos (verdadero o falso) y producen como resultado un nuevo valor booleano. Los tres operadores lógicos más importantes son «y», «o» y «no». En Java se escriben: && (y), || (o) y ! (no). La expresión a && b es verdadera si tanto a como b son verdaderas, en todos los otros casos es falsa. La expresión a || b es verdadera si alguna de las dos es verdadera, puede ser a o puede ser b o pueden ser las dos; si ambas son falsas el resultado es falso. La expresión !a es verdadera si a es falso, y es falsa si a es verdadera.

3.8.2

Concatenación de cadenas

El operador suma (+) tiene diferentes significados dependiendo del tipo de sus operandos. Si ambos operandos son números, el operador + representa la adición. Si los operandos son cadenas, el significado del signo más es la concatenación de cadenas y el resultado es una única cadena compuesta por los dos operandos. Si uno de los operandos del operador más es una cadena y el otro no, el operando que no es cadena es convertido automáticamente en una cadena y luego se realiza la concatenación correspondiente. Esta conversión funciona para todos los tipos. Cualquier tipo que se «sume» con una cadena, automáticamente es convertido a una cadena y luego concatenado.

3.8.3

El Operador Módulo

El operador módulo (%) calcula el resto de una división entera. (27%4) será 3.

3

3.9 Objetos que Crean Objetos Los objetos pueden crear otros objetos usando el operador new. La sintaxis de una operación para crear un objeto nuevo es: new NombreDeClase(lista-de-parámetros) La operación new hace dos cosas:  Crea un nuevo objeto de la clase nombrada.  Ejecuta el constructor de dicha clase. Si el constructor de la clase tiene parámetros, los parámetros actuales deben ser proporcionados en la sentencia new.

3.10 Constructores Múltiples Es común que las declaraciones de clases contengan versiones alternativas de constructores o métodos que proporcionan varias maneras de llevar a cabo una tarea en particular mediante diferentes conjuntos de parámetros. Este punto se conoce como sobrecarga de un constructor o método. Una clase puede contener más de un constructor o más de un método con el mismo nombre, siempre y cuando tengan distintos conjuntos de parámetros que se diferencien por sus tipos.

3.11 Llamadas a Métodos 3.11.1 Llamada a métodos internos Los métodos pueden llamar a otros métodos de la misma clase como parte de su implementación. Se denomina llamada a método interno. Se denomina así porque este método está ubicado en la misma clase en que se produce su llamada. Las llamadas a métodos internos tienen la siguiente sintaxis: nombreDelMétodo(lista-de-parámetros) Cuando se encuentra una llamada a un método, se ejecuta este último, y después de su ejecución se vuelve a la llamada al método y se continúa con la sentencia que sigue a la invocación. Para que la llamada a un método coincida con la signatura del mismo, deben coincidir tanto el nombre del método como su lista de parámetros.

3.11.2 Llamada a métodos externos Los métodos pueden llamar a métodos de otros objetos usando la notación de punto: se denomina llamada a método externo. La sintaxis de una llamada a un método externo es: objeto.nombreDelMétodo(lista-de-parámetros) Esta sintaxis se conoce con el nombre de “notación con punto”. Consiste en un nombre de objeto, un punto, el nombre del método y los parámetros para la llamada Es particularmente importante apreciar que usamos aquí el nombre de un objeto y no el nombre de una clase. El conjunto de métodos de un objeto que está disponible para otros objetos se denomina su interfaz.

4

3.12 Otro ejemplo de interacción de objetos 3.12.2 La Palabra Clave this Observe la siguiente sentencia con la palabra clave this: this.from = from; La línea en su totalidad es una sentencia de asignación, asigna el valor del lado derecho (from) a la variable que está del lado izquierdo (this.from) del símbolo igual (=). El motivo por el que se usa esta construcción radica en que tenemos una situación que se conoce como sobrecarga de nombres, y significa que el mismo nombre es usado por entidades diferentes. Es importante comprender que los campos de un objeto y los parámetros o variables locales son variables que existen independientemente unas de otras, aun cuando compartan nombres similares. Un parámetro o variable local y un campo que comparten un nombre no representan un problema para Java. La especificación de Java responde a esta pregunta: Java especifica que siempre se usará la declaración más cercana encerrada en un bloque. Dado que el parámetro o variable local from está declarado en el método y el campo from está declarado en la clase, se usará el parámetro pues su declaración es la más cercana a la sentencia que lo usa. Lo que necesitamos es un mecanismo para acceder a un campo cuando existe una variable con el mismo nombre declarada más cerca de la sentencia que la usa. Este mecanismo es justamente lo que significa la palabra clave this. La expresión this hace referencia al objeto actual. Al escribir this.from estamos haciendo referencia al campo del objeto actual, por lo que esta construcción nos ofrece una forma de referirnos a los campos en lugar de a los parámetros cuando tienen el mismo nombre. Ahora podemos leer la sentencia de asignación nuevamente: this.from = from; Como podemos ver, esta sentencia tiene el mismo efecto que la siguiente: campo de nombre "from" = parámetro de nombre "from"; Asigna el valor del parámetro from al campo del mismo nombre y por supuesto, esto es exactamente lo que necesitamos hacer para inicializar el objeto adecuadamente. La razón por lo que hacemos esto radica en la legibilidad del código. Si un nombre describe perfectamente la finalidad, resulta razonable usarlo como nombre de parámetro y de campo y eliminar los conflictos de nombres usando la palabra clave this en la asignación.

5

3.13 Uso del depurador, Debugger Un depurador es una herramienta de software que ayuda a examinar cómo se ejecuta una aplicación. Puede usarse para encontrar problemas. Un depurador es un programa que permite que los programadores ejecuten una aplicación paso a paso. Generalmente, ofrece funciones para detener y comenzar la ejecución de un programa en un punto seleccionado del código y para examinar los valores de las variables.

6



Interacción de Objetos ...................................................................................................................... 2  3.2 

Abstracción y Modularización ................................................................................................... 2 

3.3 

Abstracción en el Software ........................................................................................................ 2 

3.6 

Diagramas de Clases con Diagramas de Objetos ...................................................................... 2 

3.7 

Tipos Primitivos y Tipos Objeto................................................................................................ 3 

3.8 

El código fuente para ClockDisplay .......................................................................................... 3 

3.8.2 

Concatenación de cadenas .................................................................................................. 3 

3.8.3 

El Operador Módulo ........................................................................................................... 3 

3.9 

Objetos que Crean Objetos ........................................................................................................ 4 

3.10  Constructores Múltiples ............................................................................................................. 4  3.11  Llamadas a Métodos .................................................................................................................. 4  3.11.1  Llamada a métodos internos ............................................................................................... 4  3.11.2  Llamada a métodos externos .............................................................................................. 4  3.12  Otro ejemplo de interacción de objetos ..................................................................................... 5  3.12.2  La Palabra Clave this .......................................................................................................... 5  3.13  Uso del depurador, Debugger .................................................................................................... 6 

7

Capítulo 4 Ag rupar Objetos

Centro Asociado Palma de Mallorca Tutor: Antonio Rivero Cuesta 1

4 Agrupar Objetos 4.1 La colección como abstracción Una colección es una abstracción y es el concepto de agrupar cosas para poder referirnos a ellas y manejarlas de manera conjunta. Una colección puede ser grande, pequeña o vacía. Operaciones típicas son:  Añadir.  Eliminar.  Ordenar. La abstracción colección se convierte en una clase de algún tipo. Las operaciones serían los métodos de esa clase. Una colección de música Rock sería una instancia de la clase. Los elementos almacenados en una instancia de colección serían, ellos mismos, objetos. Necesitaremos una solución genérica para agrupar los objetos en colecciones. En ocasiones el número de elementos almacenados en la colección varía a lo largo del tiempo. Una solución adecuada sería aquella que no requiera que conozcamos anticipadamente la cantidad de elementos que queremos agrupar o bien, establecer un límite mayor que dicho número.

4.4 Utilización de una clase de librería Tenemos en cuenta que las clases de librería no aparecen en el diagrama de clases de BlueJ Los lenguajes orientados a objetos suelen estar acompañados de librerías de clases. Estas bibliotecas contienen varios cientos o miles de clases diferentes que han demostrado ser de gran ayuda para los desarrolladores en un amplio rango de proyectos diferentes. Java cuenta con varias de estas bibliotecas y las denomina paquetes, packages. La clase ArrayList, que es un ejemplo de una clase estándar de librería está definida en el paquete java.util. ArrayList es una clase de colección de propósito general, no está restringida en lo que respecta a los tipos de objeto que puede almacenar Las colecciones de objetos son objetos que pueden almacenar un número arbitrario de otros objetos.

4.4.1

Importación de una clase de librería

El acceso a una clase estándar de librería de Java se obtiene mediante la sentencia import, para ArrayList sería: import java.util.ArrayList; Esta sentencia hace que la clase ArrayList del paquete java.util esté disponible para nuestra clase. Las sentencias import deben ubicarse en el texto de la clase, siempre antes del comienzo de la declaración de la clase.

2

Una vez que el nombre de una clase ha sido importado desde un paquete de esta manera, podemos usar dicha clase tal como si fuera una de nuestras propias clases. Por ejemplo como en la siguiente declaración: private ArrayList files; Se lee: "una colección ArrayList de objetos tipo String" Aquí se observa una nueva estructura sintáctica: la mención de String entre símbolos de menor “”: . Cuando usamos colecciones, debemos especificar dos tipos:  El tipo propio de la colección, en este caso ArrayList.  El tipo de los elementos que planeamos almacenar en la colección, en este caso String.

4.4.2

Notación diamante

Para instanciar un nuevo objeto se necesita especificar de nuevo el tipo completo con el tipo de elemento entre los símbolos de menor y de mayor, seguido de los paréntesis para la lista de parámetros: files = new ArrayList(); Desde la versión 7 de Java el compilador puede inferir el tipo parametrizado del objeto que se está creando a partir del tipo de la variable a la que se está realizando la asignación. Se conoce como notación diamante: files = new ArrayList();

4.4.3

Principales métodos de ArrayList

La clase ArrayList declara muchos métodos entre ellos: add, size, get y remove.  add almacena un objeto en la lista.  size devuelve el número total de elementos almacenados en la lista.  get devuelve un elemento, sin eliminarlo de la colección.  remove elimina un objeto en la lista.

3

4.5 Estructuras de objetos con colecciones Características importantes de la clase ArrayList son:  Es capaz de aumentar su capacidad interna tanto como se requiera: cuando se agregan más elementos, simplemente crea el espacio necesario para ellos.  Mantiene su propia cuenta privada de la cantidad de elementos almacenados, que se obtiene mediante size.  Mantiene el orden de los elementos que se agregan, el método add almacena cada nuevo elemento al final de la lista, posteriormente se pueden recuperar en el mismo orden.

4.6 Clases genéricas La nueva notación, ArrayList, es una clase pero requiere que se especifique un segundo tipo como parámetro cuando se usa para declarar campos u otras variables. Las clases que requieren este tipo de parámetro se denominan clases genéricas. Las clases genéricas no definen un tipo único en Java sino potencialmente muchos tipos. Por ejemplo, la clase ArrayList puede usarse para especificar un ArrayList de Strings, un ArrayList de Personas, un ArrayList de Rectángulos, o un ArrayList de cualquier otra clase. Cada ArrayList en particular es un tipo distinto que puede usarse en declaraciones de campos, parámetros y tipos de retorno. private ArrayList miembros; private ArrayList misMaquinas; Estas declaraciones establecen que:  miembros contiene un ArrayList que puede almacenar objetos Persona.  misMaquinas contiene un ArrayList que almacena objetos MaquinaDeBoletos. Hay que tener en cuenta que ArrayList y ArrayList son tipos diferentes. Los campos no pueden ser asignados uno a otro, aun cuando sus tipos deriven de la misma clase.

4.7 Numeración dentro de las colecciones Los elementos almacenados en las colecciones tienen una numeración implícita o posicionamiento que comienza a partir de cero. La posición que ocupa un objeto en una colección se conoce como su índice. El primer elemento que se agrega a una colección tiene por índice al número 0, el segundo tiene al número 1, y así sucesivamente hasta size − 1. Los métodos que se utilicen deben asegurar que el valor de su parámetro se encuentre dentro del rango de valores de índice permitidos [0...size()−1]. Si se intenta acceder a un elemento de una colección que está fuera de los índices válidos del ArrayList se obtendrá un mensaje del error denominado desbordamiento, que en Java será IndexOutBoundsException.

4

4.7.1

El efecto de las eliminaciones sobre la numeración

La clase ArrayList tiene un método remove que toma como parámetro el índice del elemento o el propio elemento a eliminar. Una complicación del proceso de eliminación es que se modifican los valores de los índices de los restantes objetos que están almacenados en la colección. También es posible insertar elementos en un ArrayList en otros lugares distintos que el final de la colección. Esto significa que los elementos que ya están en la lista deben incrementar sus índices cuando se agrega un nuevo elemento. Los usuarios deben ser conscientes de estos cambios en los índices cuando agregan o eliminan notas.

4.9 Procesamiento de una colección completa A la hora de procesar una colección y realizar una determinada acción varias veces utilizaremos instrucciones de bucle o estructuras iterativas de control. Un ciclo o bucle puede usarse para ejecutar repetidamente un bloque de sentencias sin tener que escribirlas varias veces.

4.9.1

El ciclo for-each

for-each es un tipo de bucle. Las acciones de un ciclo for-each se pueden resumir en el siguiente pseudocódigo: for(TipoDelElemento elemento: colección){ cuerpo del ciclo } Consta de dos partes:  Una cabecera del bucle (la primera línea del ciclo).  Un cuerpo a continuación del encabezado. El cuerpo contiene aquellas instrucciones que queremos ejecutar una y otra vez. Una forma de entender este bucle sería: para cada elemento en la colección hacer: { cuerpo del bucle } En cada vuelta, antes de que la sentencia se ejecute, la variable elemento se configura para contener uno de los elementos de la lista: primero el del índice 0, luego el del índice 1, y así sucesivamente. La palabra clave for inicia el bucle, seguida por un par de paréntesis en los que se definen los detalles del bucle, lo primero vemos TipoDelElemento elemento, que declara una variable local elemento que se usará para almacenar los distintos elementos de la lista. Llamaremos variable de bucle a la variable que se usará para almacenar los elementos de la lista. El tipo de la variable de bucle debe ser el mismo que el tipo del elemento declarado para la colección que estamos usando, a continuación aparecen dos puntos y la variable que contiene la colección que deseamos procesar. Cada elemento de esta colección será asignado en su turno a la variable de bucle, y para cada una de estas asignaciones el cuerpo del bucle se ejecutará una sola vez. 5

4.10 Iteración Indefinida Una acción se repetirá un número de veces no predecible hasta que se complete la tarea.

4.10.1 El bucle while Un bucle while consta de una cabecera y de un cuerpo, el cuerpo puede ejecutarse repetidamente. La estructura de un bucle while sería: while (condición booleana){ cuerpo del ciclo } El ciclo while comienza con la palabra clave while, seguida de una condición booleana. Este ciclo es más flexible que el ciclo for-each. Puede recorrer un número variable de elementos de la colección, dependiendo de la condición del bucle. La condición booleana es una expresión lógica que se usa para determinar si el cuerpo debe ejecutarse al menos una vez. Si la condición se evalúa verdadera, se ejecuta el cuerpo del ciclo. Cada vez que se ejecuta el cuerpo del ciclo, la condición se vuelve a controlar nuevamente. Este proceso continúa repetidamente hasta que la condición resulta falsa, que es el punto en el que se salta del cuerpo del ciclo y la ejecución continúa con la sentencia que esté ubicada inmediatamente después del cuerpo.

4.10.2 Iteración mediante una variable índice Utilizar un bucle while requiere más esfuerzo de programación: Hay que declarar fuera del bucle una variable para el índice e iniciarlo por nuestros propios medios a 0 para acceder al primer elemento de la lista. La condición tiene que estar bien definida, sino el bucle será infinito. También tenemos que llevar nuestra propia cuenta del índice para recordar la posición en que estábamos. Existe un operador especial para incrementar una variable numérica en 1: variable++; Que es equivalente a: variable = variable + 1; Hay dos puntos más a destacar sobre el bucle while:  No necesita estar relacionado con una colección.  No necesitamos procesar cada uno de sus elementos de la colección. Una ventaja de tener una variable de índice explícita es que podemos utilizar su valor tanto dentro como fuera del bucle. Una variable de índice local nos resultará útil a la hora de realizar búsquedas en una lista:  Nos proporciona información dónde está ubicado el elemento  Podemos hacer que esta información siga estando disponible una vez que el bucle haya finalizado.

6

4.10.3 Búsquedas en una colección La característica clave de una búsqueda infinita es que implica una iteración indefinida. En situaciones reales de búsqueda consideramos dos posibilidades:  La búsqueda tiene éxito después de un número indefinido de iteraciones.  La búsqueda falla después de agotar todas las posibilidades. Uno de estos dos criterios debe evaluar la condición como false para detener el bucle.

4.10.4 Algunos ejemplos no relacionados con colecciones Los bucles podemos utilizarlos en situaciones distintas a la iteración de una colección. Los bucles each-for no son válidos para este propósito. Podemos usar el bucle while o el bucle for.

4.12 El tipo iterador Existe una tercera variante para recorrer una colección, que está entre medio de los ciclos while y for-each. Usa un ciclo while para llevar a cabo el recorrido y un objeto iterador en lugar de una variable entera como índice para controlar la posición dentro de la lista. Iterator, con la I mayúscula es un tipo de Java, también existe el método iterator. Un iterador es un objeto que proporciona funcionalidad para recorrer todos los elementos de una colección. El método iterator de ArrayList devuelve un objeto Iterator. La clase Iterator también está definida en el paquete java.util. Para poder utilizarlo: Import java.util.ArrayList; Import java.util.Iterator; Un Iterator provee dos métodos para iterar una colección: hasNext y next. La manera de uso en pseudocódigo sería: Iterator it = miColeccion.iterator (); while (it.hasNext ( )) { Invocar it. next () para obtener el siguiente elemento Hacer algo con dicho elemento } Iterator también es de tipo genérico por lo que hay que parametrizarlo con el tipo de los elementos de la colección. Luego usamos dicho iterador para controlar repetidamente si hay más elementos it.hastNext() y para obtener el siguiente elemento it.next(). Un punto a destacar es que le pedimos al iterador que devuelva el siguiente elemento y no a la colección. La llamada a next hace que el objeto Iterator devuelva el siguiente elemento de la colección y luego avance más allá de ese elemento. 7

4.12.1 Comparación entre los iteradores y el acceso mediante índices El bucle for-each, es la técnica estándar que se usa si deben procesarse todos los elementos de una colección porque es el más breve para este caso, pero la menos flexible. El bucle while (con un índice y el método get) y el iterador tienen la ventaja de que la iteración puede ser detenida más fácilmente en mitad del proceso, de modo que son mejores cuando se quiere procesar sólo una parte de una colección. Para algunas colecciones, es imposible o muy ineficiente acceder a elementos individuales mediante un índice y se accede mediante for-each o iterador. El Iterator está disponible para todas las colecciones de las clases de las bibliotecas de Java y es un patrón importante que se usará a menudo.

4.12.2 Eliminación de elementos Puede darse el caso que necesitemos eliminar elementos de la colección mientras estamos iterando. La solución apropiada es utilizar un Iterator. Tiene un tercer método, remove. No admite ningún parámetro y tiene un tipo de retorno void. Invocar a remove hará que sea eliminado el elemento devuelto por la llamada más reciente a next. Este tipo de eliminación no es posible con el bucle for-each ya que no dispone de un Iterator con el que trabajar. Podemos utilizar el bucle while con un Iterator.

4.14 Otro ejemplo: un sistema de subastas 4.14.1 La palabra clave null. La palabra clave null se usa para significar que «no hay objeto», es decir cuando una variable objeto no está haciendo referencia realmente ningún objeto. Un campo que no haya sido inicializado explícitamente contendrá el valor por defecto null.

4.14.5 Objetos anónimos La siguiente sentencia ilustra el uso de objetos anónimos: miColeccion.add(new Elemento()); Aquí estamos haciendo dos cosas:  Crear un nuevo objeto Elemento  Pasar este nuevo objeto al método add de miColeccion. Podríamos haber escrito lo mismo en dos líneas de código, una para declarar el nuevo elemento y otra para pasárselo a la colección. Ambas versiones son equivalentes, pero la primera versión evita declarar una variable que puede tener un uso muy limitado. Se crea un objeto anónimo, un objeto sin nombre, pasándoselo directamente al método que lo utiliza. Dos objetos String s1 y s2 pueden compararse para ver si son iguales mediante la expresión lógica: s1.equals(s2).

8

4.16 Colecciones de tamaño fijo A veces conocemos anticipadamente cuántos elementos deseamos almacenar en la colección y este número permanece invariable durante la vida de la colección. En estas circunstancias, tenemos la opción de utilizar una colección de objetos de tamaño fijo. Una colección de tamaño fijo se denomina array o vector. Un vector es un tipo especial de colección que puede almacenar un número fijo de elementos. Se obtienen ventajas con respecto a las clases de colecciones de tamaño flexible:  El acceso a los elementos de un vector es generalmente más eficiente que el acceso a los elementos de una colección de tamaño flexible.  Los vectores son capaces de almacenar objetos o valores de tipos primitivos. Las colecciones de tamaño flexible sólo pueden almacenar objetos.

4.16.2 Declaración de variables vectores La característica distintiva de la declaración de una variable de tipo vector es un par de corchetes que forman parte del nombre del tipo: int[]. Este detalle indica que la variable declarada es de tipo vector de enteros. Decimos que int es el tipo base de este vector en particular. La declaración de una variable vector no crea en sí misma un objeto vector, sólo reserva un espacio de memoria para que en un próximo paso, usando el operador new, se cree el vector tal como con los otros objetos.

4.16.3 Creación de objetos vector La siguiente sentencia muestra como se asocia una variable vector con un objeto vector: obejetoVector = new int[tamaño]; La forma general de la construcción de un objeto vector es: new tipo[expresión-entera] La elección del tipo especifica de qué tipo serán todos los elementos que se almacenarán en el vector. La expresión-entera especifica el tamaño del vector. Cuando se asigna un objeto vector a una variable vector, el tipo del objeto vector debe coincidir con la declaración del tipo de la variable. Cuando se crea un vector no crea tantos objetos como tiene capacidad para almacenar, solo crea una colección de tamaño fijo que es capaz de almacenar dichos objetos.

4.16.4 Utilizar objetos de vector Se accede a los elementos individuales de un objeto vector mediante un índice. Un índice es una expresión entera escrita entre un par de corchetes a continuación del nombre de una variable vector. Los valores válidos para una expresión que funciona como índice dependen de la longitud del vector en el que se usarán. Los índices de los vectores siempre comienzan por cero y van hasta el valor del tamaño del vector menos uno. 9

Las expresiones que seleccionan un elemento de un vector se pueden usar en cualquier lugar que requiera un valor del tipo base del vector. Esto quiere decir que podemos usarlas, por ejemplo, en ambos lados de una asignación. El uso de un índice de un vector en el lado izquierdo de una asignación es equivalente a un método mutador (o método set) del vector porque cambiará el contenido del mismo. Los restantes usos del índice son equivalentes a los métodos selectores (o métodos get).

4.16.5 El bucle for Java define dos variantes para el ciclo for, el bucle for-each, y el bucle for, que es una estructura de control repetitiva alternativa que resulta particularmente adecuada cuando:  Queremos ejecutar un conjunto de sentencias un número exacto de veces.  Necesitamos una variable dentro del ciclo cuyo valor cambie en una cantidad fija, generalmente en 1, en cada iteración. Es común el uso del ciclo for cuando queremos hacer algo con cada elemento de un vector tal como imprimir el contenido de cada elemento. Un ciclo for tiene la siguiente forma general: for(inicialización;condición;incremento){ instrucciones a repetir } En este ciclo for, los paréntesis contienen tres secciones distintas separadas por símbolos de punto y coma (;). Su equivalente while: Inicialización; while (condición){ Instrucciones a repetir incremento } Todos los vectores contienen un campo length que contiene el valor del tamaño del vector. El valor de este campo coincide siempre con el valor entero usado para crear el objeto vector. Por eso la condición del bucle suele usar el operador menor que “

Get in touch

Social

© Copyright 2013 - 2024 MYDOKUMENT.COM - All rights reserved.