manual de smalltalk

76
Manual de Smalltalk Desarrollo y ejemplificación de los conceptos del Paradigma de Objetos Paradigmas de Programación Facultad Regional Buenos Aires Universidad Tecnológica Nacional Ing. Lucas Spigariol

Upload: caca-popo

Post on 22-Jun-2015

5.985 views

Category:

Documents


18 download

TRANSCRIPT

Page 1: Manual de Smalltalk

Manual de Smalltalk

Desarrollo y ejemplificación de los conceptos

del Paradigma de Objetos

Paradigmas de Programación

Facultad Regional Buenos Aires

Universidad Tecnológica Nacional

Ing. Lucas Spigariol

Page 2: Manual de Smalltalk

Manual de Smalltalk - Ing. Lucas Spigariol

ContenidoCapítulo 1: Un Vistazo al Paradigma de Objetos

¿Qué es la Programación Orientada a Objetos? Conceptos centrales del Paradigma de Objetos Smalltalk

Capítulo 2: Objetos, Mensajes y Clases Objetos y Clases Envío de Mensajes Métodos de clase Self

Capítulo 3: Instrucciones Smalltalk Instrucciones Asignación Devolución de Valores Comentarios Variables Temporales Estructura Básica de un Método Bloques Mensajes en Cascada

Capítulo 4: Operaciones con Datos Literales Operaciones Aritméticas Nil True y False Comparaciones Lógicas Lógica Condicional Iteraciones

Capítulo 5: Herencia ¿Qué es la herencia? Herencia de Métodos Herencia de Variables Variables de Clase Clases Abstractas Super vs. Self

Capítulo 6: Colecciones ¿Qué es una Colección? Colecciones Comunes Mensajes a las Colecciones Colecciones Especiales

Glosario

Página 2

Page 3: Manual de Smalltalk

Manual de Smalltalk - Ing. Lucas Spigariol

Capítulo 1:

Un Vistazo al Paradigma de Objetos

¿Qué es la Programación Orientada a Objetos?

La Programación Orientada a Objetos (POO) es diferente de los lenguajes de programación procedurales (C, Cobol, Pascal, etc.). Todo en POO está conceptualizado como "objetos" (ver Abstracción de datos). La POO, definida en su más puro sentido, es implementada por el envío de mensajes a los objetos. Para entender este concepto, primero debemos conocer qué es un objeto.

¿Qué es un Objeto?

Un objeto puede ser considerado una "cosa" que puede realizar un conjunto de actividades. El conjunto de actividades que un objeto puede realizar define el comportamiento del objeto. Por ejemplo, un objeto "EstadoAlumno" puede informarle su promedio, año de escuela, etc.; o puede agregar una lista de las materias cursadas. Un objeto "Alumno" puede informarle su nombre o su dirección.

La interfase del objeto consiste en un conjunto de comandos, cada comando desarrolla una acción específica. Un objeto puede pedirle a otro objeto que realice una acción, enviándole un mensaje. El objeto que envía el mensaje es designado emisor y el objeto que recibe el mensaje es designado receptor.

Página 3

Page 4: Manual de Smalltalk

Manual de Smalltalk - Ing. Lucas Spigariol

El control le es dado al objeto receptor hasta que complete la acción; luego el control regresa al objeto emisor.

Por Ejemplo, un objeto Escuela le pide al objeto Alumno su nombre enviándole un mensaje preguntándole por su nombre. El objeto receptor Alumno devuelve su nombre al objeto emisor.

Un mensaje también puede contener información que los objetos emisores necesitan pasar al objeto receptor, a esta información se la llama argumento de un mensaje. Un objeto receptor siempre devuelve un valor al objeto emisor. Este valor devuelto puede ser, o no, útil al objeto emisor.

Por ejemplo, el objeto Escuela ahora desea cambiar el nombre del alumno. Esto lo hace enviando al objeto Alumno un mensaje para cambiar su nombre a uno nuevo. El nuevo nombre es pasado como un argumento en el mensaje. En este caso, al objeto Escuela no le interesa el valor que devuelva el mensaje.

Página 4

Page 5: Manual de Smalltalk

Manual de Smalltalk - Ing. Lucas Spigariol

Operación Secuencial

Es muy común que un mensaje provoque el envío de otros mensajes, ya sea al mismo u otros objetos, para completar su tarea. A esto se lo llama operación secuencial. El control no le será devuelto al objeto emisor original hasta que todos los otros mensajes hayan sido completados. Por ejemplo, el siguiente diagrama, el Objeto A envía un mensaje al Objeto B. Para que el Objeto B procese este mensaje, envía otro mensaje al Objeto C. Asimismo el Objeto C envía otro mensaje al Objeto D. El Objeto D devuelve el control al Objeto C, asimismo el Objeto C devuelve el control al Objeto B que, a su vez, lo devuelve al Objeto A. El control no es devuelto al Objeto A hasta que todos los otros mensajes se han completado.

Método

¿Cómo los objetos receptores interpretan los mensajes de los objetos emisores? ¿Cómo se procesan los mensajes?

Cada mensaje posee un código asociado a él. Cuando un objeto recibe un mensaje, su código es ejecutado. En otras palabras, estos mensajes determinan el comportamiento de un objeto y el código determina cómo, el objeto, lleva a cabo cada mensaje. El código que está asociado a cada mensaje se llama método. El nombre del mensaje, también suele llamarse el nombre del método debido a su asociación con el método.

Cuando un objeto recibe un mensaje, determina qué método es el solicitado y pasa el control al método. Un objeto tiene tantos métodos como acciones se desea que tenga.

Observe el siguiente diagrama, nombre, nombre:, direccion y nombre:direccion: son nombres de métodos para el objeto Alumno. Cuando el objeto Alumno recibe el mensaje nombre, el mensaje nombre pasa el control al método nombre definido en Alumno.

Página 5

Page 6: Manual de Smalltalk

Manual de Smalltalk - Ing. Lucas Spigariol

Los métodos que operan sobre objetos específicos son los métodos de instancias, y los mensajes que invocan métodos de instancia se llaman mensajes de instancia.

Los métodos son similares a las subrutinas, procedimientos o funciones que se encuentran en los lenguajes procedurales (C, Pascal). Por ejemplo, un nombre de método equivale al nombre de una subrutina, y el código del método equivale al código de la subrutina. El envío de mensajes a objetos es similar al llamado de subrutinas.

Datos de un Objeto

Cada objeto necesita guardar la información sobre cómo realizar su comportamiento definido. Algunos objetos también contienen variables que soportan su comportamiento. Estas variables son llamadas variables de instancia. Sólo el método de instancia de un objeto puede referirse y modificar los valores guardados en las variables de instancia. Los métodos de instancia de los objetos no pueden referirse a los datos de otros objetos. Un objeto sólo puede acceder a los datos de otro objeto enviándole mensajes. A esto se lo llama encapsulamiento y asegura que el proceso para obtener los datos de un objeto sea seguro.

Observe el siguiente diagrama, las variables de instancia variableUno hasta variableX sólo pueden ser accedidas por el emisor a través de los métodos de instancia métodoUno hasta métodoN. El emisor no puede referirse a las variables, directamente, por sí mismo.

Página 6

Page 7: Manual de Smalltalk

Manual de Smalltalk - Ing. Lucas Spigariol

A diferencia de la programación procedural, donde las áreas de datos de uso común son utilizadas para compartir información, la programación orientada a objetos no aprueba el acceso directo a los datos de uso común (exceptuando el uso de las variables globales) por otros programas. Sólo el objeto que "posee" los datos puede cambiar su contenido. Otros objetos pueden ver o cambiar estos datos enviando mensajes al "dueño".

Los nombres de variables de instancia pueden ser idénticos a los nombres de los métodos que están asociados a ellos. Por ejemplo, el objeto Alumno tiene los métodos nombre, dirección, y carrera así como también las variables de instancia nombre, dirección, y carrera. Smalltalk distingue entre los identificadores de variables y los identificadores de métodos a través de la posición que ocupan en la expresión.

Conceptos centrales del Paradigma de Objetos

Un lenguaje de computación está orientado a los objetos si soporta las cuatro propiedades específicas de los objetos, llamadas abstracción, polimorfismo, herencia, y encapsulamiento. La correcta aplicación de estos conceptos permite obtener un alto nivel de reutilización de las soluciones.

Una de las características más importantes de la programación orientada a objetos es la habilidad para modificar las soluciones existentes para resolver nuevos problemas. Si un tipo particular de problema ha sido resuelto utilizando la POO, un problema similar, aunque diferente, puede ser resuelto haciendo algunos cambios en el protocolo del objeto-mensaje ya existente. La mayoría del tiempo, esto requiere agregar nuevos mensajes. En otros casos puede requerir agregar nuevos objetos y nuevos mensajes a los que responden los nuevos objetos.

Página 7

Page 8: Manual de Smalltalk

Manual de Smalltalk - Ing. Lucas Spigariol

La reutilización es, probablemente, la más importante característica del paradigma orientado de Objetos. Si bien los lenguajes procedurales también pueden ser reutilizados, los lenguajes de Objetos hacen la reutilización no sólo mucho más fácil, sino que la consideran como intrínseca de la configuración del lenguaje.

Abstracción de Datos

La abstracción de datos permite diferenciar entre el comportamiento de un objeto (la acción que es capaz de realizar) y cómo lleva a cabo este comportamiento. Esta abstracción de datos se implementa a través de una interfase de objeto.

A través de esta interfase un objeto emisor se comunica con otro objeto receptor, pero el objeto emisor desconoce la forma en que se lleva a cabo la acción solicitada (mensaje).

Encapsulamiento

En la programación orientada a objeto, los objetos interactúan entre ellos a través de los mensajes. Lo único que un objeto conoce de otro es su interfase. Los datos y lógica de un objeto están ocultos a los otros objetos. O sea, la interfase encapsula los datos y código de un objeto.

Esto permite al programador separar la implementación de un objeto, de su comportamiento. Esta separación crea una "caja negra" en donde el usuario está alejado de los cambios de la implementación. Mientras la interfase permanezca igual, cualquier cambio interno a la implementación es transparente al usuario. Por ejemplo, si el mensaje nombre es enviado al objeto Alumno, al usuario no le importa cómo el programador implementó el código que maneja este mensaje. El programador puede cambiar la implementación en cualquier momento, pero el mensaje nombre aún debería trabajar ya que la interfase es la misma.

Página 8

Page 9: Manual de Smalltalk

Manual de Smalltalk - Ing. Lucas Spigariol

Polimorfismo

Otro beneficio que surge al separar la implementación del comportamiento es el polimorfismo. El polimorfismo permite a dos o más objetos responder al mismo mensaje. Un método llamado nombre también podría ser implementado en un objeto de la clase Curso. Aunque la implementación de este mensaje nombre devolvería el número de curso y su nombre, su protocolo es el mismo que el mensaje nombre del objeto Alumno. El polimorfismo permite a un objeto emisor comunicarse con diferentes objetos de una manera consistente sin tener que preocuparse sobre las diferentes implementaciones de un mensaje.

Una analogía del polimorfismo con la vida diaria es cómo los alumnos responden al timbre de la escuela. Todos los alumnos conocen el significado del timbre. Cuando el timbre (mensaje) suena, sin embargo, tiene su propio significado para cada alumno (objeto). Algunos alumnos irán a casa, otros a la biblioteca, y otros irán a clases. Cada alumno responde al timbre, pero su respuesta puede ser diferente.

Otro ejemplo del polimorfismo es la función de imprimir. Cada objeto que puede ser impreso debe conocer como imprimirse. El mensaje es el mismo a todos los diferentes objetos: print, pero la implementación sobre qué deben hacer para imprimirse a sí mismos varía.

El objeto emisor no necesita conocer cómo el objeto receptor implementa el mensaje. Sólo el objeto receptor se preocupa de ello. Suponga que existe un método printPage en un objeto Documento que tiene la responsabilidad de imprimir una página. Para imprimir una página, el método printPage envía el mensaje print a cada objeto de página. El objeto Documento no necesita conocer qué tipos de objetos están en la página, sólo que cada uno soporta el comportamiento de la impresión.

Nuevos objetos pueden ser agregados a la página sin afectar el método printPage. Este método sigue enviando el mensaje print y el nuevo objeto provee su propio método print en respuesta a ese mensaje.

El polimorfismo permite al objeto emisor comunicarse con los objetos receptores sin tener que comprender qué tipo de objeto es, siempre y cuando el objeto receptor soporte los mensajes.

Página 9

Page 10: Manual de Smalltalk

Manual de Smalltalk - Ing. Lucas Spigariol

Herencia

Otro concepto importante de la programación orientada a objetos es la herencia. La herencia permite a una clase tener el mismo comportamiento que otra y extender o limitar ese comportamiento para proveer una acción especial a una necesidad específica.

Suponga la siguiente aplicación. La clase Graduado y la clase SinGraduar tienen comportamiento similar, como por ejemplo, el manejo de nombre, dirección, carrera, promedio, etc. En vez de colocar este comportamiento en ambas clases, el comportamiento es colocado en una nueva clase llamada Alumno. Ambas clases Graduado y SinGraduar se vuelven subclases de la clase Alumno, y ambas heredan el comportamiento de Alumno.

Ambas clases Graduado y SinGraduar pueden agregar comportamiento adicional que sea único a ellas. Por ejemplo, Graduado puede ser tanto para un doctorado o una carrera de postgrado. Por otro lado, la clase SinGraduar puede querer conocer cómo un cierto alumno va en la carrera.

Las clases que heredan de otras clases se llaman subclases. La clase, de la que una subclase hereda, es llamada superclase. En el ejemplo, Alumno es una superclase de Graduado y SinGraduar. Graduado y SinGraduar son subclases de Alumno.

Smalltalk

Smalltalk es un modelo puro orientado a objetos lo que significa que todo, en el entorno, es tratado como un objeto. Entre todos los lenguajes orientados a objetos, Smalltalk es el más consistente en cuanto al manejo de las definiciones y propiedades del paradigma orientado a objetos.

Smalltalk es más que un lenguaje, es un extenso programa de entorno de desarrollo con numerosos clases y métodos.

Las distintas versiones de Smalltalk presentan completos entornos de desarrollo para la implementación de aplicaciones orientadas a objetos. Los Smalltalk más comunes y simples de utilizar consisten de los siguientes componentes:

Un modelo de objeto a partir del cual los objetos están definidos: El modelo de objeto define cómo se comportan los objetos. Este modelo soporta la herencia, el comportamiento de

Página 10

Page 11: Manual de Smalltalk

Manual de Smalltalk - Ing. Lucas Spigariol

clases e instancias, la asociación dinámica (binding dinámico), el manejo de mensajes, y las colecciones.

Un conjunto de clases reutilizables: Smalltalk tiene una gran cantidad de clases que pueden ser reutilizadas en cualquier programa Smalltalk. Estas clases proveen las funciones básicas en Smalltalk, además del soporte para la portabilidad a diferentes plataformas, incluyendo la portabilidad de las interfaces gráficas de usuario; también se encargan de la definición y manejo de las clases. Existe un núcleo de clases estándar compartidas por los más conocidos fabricantes, a la que se agregan otras clases que permiten realizar funcionalidades específicas.

Un conjunto de herramientas de desarrollo: Estas herramientas habilitan a los usuarios a mirar y modificar las clases existentes, renombrar clases, agregar nuevas clases, y borrar clases. También proveen detección de errores a nivel fuente, incluyendo la habilidad de poder realizar seguimientos, observar datos, modificar datos, y realizar cambios al código en tiempo de ejecución de un programa.

Un entorno en tiempo de ejecución: Esto permite a los usuarios a ejecutar un programa en Smalltalk mientras se cambia el código fuente. Los cambios realizados al código fuente son reflejados instantáneamente en la aplicación que se está ejecutando.

Una de las mejores características de Smalltalk es el alto grado de reutilización. Smalltalk contiene un gran conjunto de objetos que pueden ser utilizados directamente, o fácilmente modificados para satisfacer la necesidad de una aplicación en general. Lo objetos suelen ser utilizados en más de una aplicación. Esto permite una mejora en la productividad, y una calidad en la zona de trabajo.

Página 11

Page 12: Manual de Smalltalk

Manual de Smalltalk - Ing. Lucas Spigariol

Capítulo 2:

Objetos, Clases y Mensajes

Presentación sintética:

Todo el procesamiento de Smalltalk consiste en el envío de mensajes a objetos. Los tres tipos de mensajes son: unarios, binarios, y de palabra clave.

Los métodos que están definidos en una Clase determinan el comportamiento de los mensajes de esa clase

Una expresión general en Smalltalk consiste en el nombre del objeto que recibe el mensaje, seguido del nombre del mensaje y sus argumentos (si los tuviera).

Objetos y Clases

Existen muchos objetos en el entorno Smalltalk. Los objetos que responden a los mismos mensajes con el mismo comportamiento y que tienen la misma estructura interna de datos, se clasifican juntos en lo que se denomina una Clase. Es la Clase la que determina como es y cómo actúa cada objeto. Todo Objeto es instancia de alguna clase en particular.

En Smalltalk todo es un objeto, incluyendo la definición de una clase, que es una instancia de una clase llamada Metaclase. Sin entrar en detalles de las implementaciones es importante tener en cuenta que una clase, en su esencia, también es un objeto y en consecuencia también se comporta como tal.

Programar en Smalltalk consiste en crear nuevas clases, crear instancias de clases, y especificar una secuencia de intercambios de mensajes a través de todos estos objetos.

Creación de una Clase

Página 12

Page 13: Manual de Smalltalk

Manual de Smalltalk - Ing. Lucas Spigariol

Las clases son creadas en el entorno de desarrollo, usando uno de los examinadores (browsers) de clases o aplicaciones. Los pasos a seguir, son los siguientes:

Seleccione la clase que será "padre" o superclase de la nueva clase.

Solicite agregar una nueva clase. Cuando se le pida ingrese el nombre de la nueva clase, no

olvide que la primera letra del nombre debe estar en mayúscula.

Cuando se le pida el tipo de subclase, seleccione subclase.

Cuando termine, la ventana del examinador mantendrá una expresión en el área de texto. Esta expresión fue utilizada para crear la clase. Ahora puede ser modificada para cambiar y extender la clase. Tenga en cuenta que los cuatro pasos aquí descritos pueden variar levemente para cada plataforma particular de Smalltalk.

Para ver un ejemplo concreto de la creación de una clase suponga que la expresión para una nueva clase es TrenElectrico, un juego compuesto por los trenes, vías, cruces, etc.; todo lo necesario para armar un circuito por donde pasa el tren eléctrico. ¿Cómo aparecerá en el examinador?, de la siguiente manera:

Object subclass: #TrenElectrico instanceVariableNames: ' ' classVariableNames: ' ' poolDictionaries: ' '

Las variables de instancia se agregan por medio del ingreso de sus nombres entre las comillas simples, que se encuentran después de instanceVariableNames:.

Object subclass: #TrenElectrico instanceVariableNames: 'motor carros casas vías cruces ' classVariableNames: ' ' poolDictionaries: ' '

Si la nueva clase TrenElectrico tuviera uno o muchos diccionarios compartidos y/o variables de clase, se agregarán de la misma forma que antes, entre las comillas simples que siguen a poolDicionaries y a classVariableNames, respectivamente. Con estos cambios, el examinador presentará lo siguiente:

Object subclass: #TrenElectrico instanceVariableNames: 'motor carros casas vías cruces' classVariableNames: ' DiagramaDeVías ' poolDictionaries: ' Trenes '

Página 13

Page 14: Manual de Smalltalk

Manual de Smalltalk - Ing. Lucas Spigariol

Envío de Mensajes

Los mensajes a los que un objeto puede responder están definidos en el protocolo de su clase. El cómo estos mensajes se ejecutan o son implementados está definido en los métodos de la clase. Los métodos dan los detalles de implementación para los mensajes, y representan el comportamiento de la clase.

Todo el procesamiento de Smalltalk se realiza por medio del envío de mensajes a objetos. Un enfoque inicial de la resolución de problemas, en Smalltalk, es tratar de reutilizar los mensajes y objetos existentes. El programador de Smalltalk, trabaja para desarrollar una secuencia objeto-mensaje que proveerá la solución deseada.

Por convención, todos los nombres de clases comienzan con una letra en mayúscula, como por ejemplo "Alumno". Los nombres de mensajes comienzan con una letra en minúscula y pueden tener cualquier combinación de letras y números sin espacios en blanco. Cuando el nombre de un mensaje contiene más de una palabra, las palabras extras comienzan con una letra en mayúscula. Un nombre válido de mensaje podría ser "unMensaje" o "miDirección."

Un mensaje como "dame tu nombre" podría ser "dameTuNombre". Sin embargo se trata de acortar los nombres de mensajes, pues es muy difícil trabajar con nombres largos; por lo tanto el nombre de mensaje adecuado sería "nombre".

Formato de un Mensaje

En general, una expresión Smalltalk consiste en el nombre del objeto que recibe el mensaje, seguido por el nombre del mensaje.

Por ejemplo:

unObjeto unMensaje

Para aquellos mensajes que necesitan pasar argumentos al objeto receptor, como los mensajes de palabra clave, al nombre del objeto receptor le sigue el nombre del mensaje y su argumento. Los argumentos se separan por medio de un espacio en blanco.

unObjeto unNumero: 1 unNombre: 'Pedro'

Existen tres tipos de mensajes: unarios, binarios y de palabra clave.

Página 14

Page 15: Manual de Smalltalk

Manual de Smalltalk - Ing. Lucas Spigariol

Mensajes Unarios

Un mensaje Unario es similar a la llamada de una función con parámetro único. Este tipo de mensaje consiste de un nombre de mensaje y un operando. Los objetos se colocan antes del nombre del mensaje. Los siguientes son ejemplos de mensajes unarios:

x sin "devuelve el resultado de sen(x)" Date tomorrow "devuelve una nueva instancia de la clase Date" 5 factorial "devuelve el factorial de 5" 'hola' outputToPrinter "Envía la cadena 'hola' a la impresora"

En estos ejemplos 'x', 'Date', '5', y 'hola' son objetos y 'sin', 'tomorrow', 'factorial', y 'outputToPrinter' son nombres de mensajes.

Mensajes Binarios

Los mensajes Binarios son utilizados para especificar operaciones aritméticas, lógicas y de comparación. Un mensaje binario puede ser de uno o dos caracteres de longitud y puede contener cualquier combinación de los siguientes caracteres especiales:

+ / \ * ~ < > = @ % | & ? ! ,

Lo siguientes son ejemplos de expresiones en Smalltalk, utilizando mensajes binarios:

a + b "devuelve la suma de a y b" a | b "devuelve la comparación lógica a o b" a >= b "compara si a es mayor o igual que b, y devuelve true (verdadero) o false (falso)"

El primer ejemplo puede también ser interpretado como "el mensaje '+' se envía al objeto 'a' con el parámetro 'b'".

Mensajes de Palabra Clave

Un mensaje de Palabra Clave es equivalente a una llamada de un procedimiento con dos o más parámetros. Observe el siguiente ejemplo, el nombre del objeto, al cual el mensaje es enviado, se escribe primero, luego el nombre del mensaje (o nombre del método) y luego el parámetro que se pasa.

unObjeto unMensaje: parametro

Página 15

Page 16: Manual de Smalltalk

Manual de Smalltalk - Ing. Lucas Spigariol

Los dos puntos (:) son una parte esencial del nombre del mensaje. Cuando hay más de un parámetro, el nombre del mensaje debe aparecer para cada parámetro.

Por ejemplo:

unObjeto unNombre1: parametro1 unNombre2: parametro2 o unObjeto es el objeto receptor o unNombre1: es la primera parte del nombre del mensaje o parametro1 es pasado a unNombre1: o unNombre2: es la segunda parte del nombre del

mensaje o parametro2 es pasado a unNombre2:

unDia month: esteMes year: esteAnio "Establece los datos privados del objeto

UnDia a month = esteMes y year = esteAnio"

alumno nombre: 'Juan' direccion: 'Junín 51' "Establece el valor de las variables de

instancia del objeto Alumno de acuerdo

a los parámetros"

Orden de Ejecución de los Mensajes

Las reglas que usa Smalltalk en la decisión del orden de ejecución de los mensajes, puede resumirse en los siguientes pasos:

1. Smalltalk ejecuta mensajes de izquierda a derecha. 2. El resultado de un mensaje reemplaza al mensaje en la

sentencia. 3. Smalltalk ejecuta primero todas las expresiones que aparecen

entre paréntesis, comenzando por la izquierda, y por aquella que está más anidada.

4. Dentro de una expresión, los mensajes unarios se ejecutan primero, luego los mensajes binarios, y finalmente los mensajes de palabra clave; siempre de izquierda a derecha.

5. Smalltalk ejecuta todos los mensajes binarios de izquierda a derecha, independientemente de las operaciones que realicen. Esto significa que no hay un orden especial para ejecutar operaciones aritméticas.

6. Una expresión puede incluir el nombre de una variable. Smalltalk reemplaza el nombre de la variable con el objeto al que ella apunta.

Página 16

Page 17: Manual de Smalltalk

Manual de Smalltalk - Ing. Lucas Spigariol

Métodos de clase

Un método de clase es la implementación de un mensaje cuyo receptor es la clase misma. Los métodos de clase proveen un comportamiento de clase. Tienen las mismas convenciones de nombramiento que los métodos de instancia.

Uno de los principales usos de los métodos de clase, es poder crear nuevas instancias de una clase.

La siguiente instrucción envía el mensaje de clase new a la clase Alumno. Cada clase contiene el mensaje new. El mensaje new retorna una nueva instancia.

Alumno new

En el siguiente ejemplo, la variable miAlumno apunta al nuevo objeto Alumno:

miAlumno := Alumno new

En Smalltalk, la expresión := es la sintaxis para la función de asignación. La variable de la izquierda apunta al resultado de la expresión de la derecha.

Una vez ejecutada la sentencia de arriba, los mensajes pueden ser enviados a miAlumno, que apunta a una instancia del objeto Alumno.

Por ejemplo:

miAlumno nombre: 'Luis' miAlumno nombre

Self

Considere la siguiente sentencia:

miAlumno nombre: 'Pedro' direccion: 'Medrano 951'

La sentencia envía el mensaje name:address: al objeto Alumno apuntado por la variable miAlumno. En vez de duplicar el código que ya existe en los métodos nombre: y direccion:, el método nombre:direccion: se implementa ejecutando los métodos nombre: y direccion:. Dado que nombre: y direccion: son métodos del mismo objeto que nombre:direccion:, debe existir alguna forma para que un método pueda referirse al objeto en el cual existe.

Página 17

Page 18: Manual de Smalltalk

Manual de Smalltalk - Ing. Lucas Spigariol

Este es el propósito de self. Un método puede acceder otros métodos en su propio objeto especificando self como el receptor del mensaje.

Observe el código para estos tres métodos:

nombre: unNombre nombre := unNombre

direccion: unaDireccion direccion := unaDireccion

nombre: unNombre direccion: unaDireccion self nombre: unNombre. self direccion: unaDireccion

El uso de self hace que Smalltalk envíe los mensajes nombre: y direccion: a la instancia actual de Alumno, la misma instancia que recibió el mensaje nombre:direccion:.

En el ejemplo, los métodos nombre: y direccion: definieron sus variables temporales con el mismo nombre que las definió el método nombre:direccion:. No hay ninguna relación entre estos nombres y no están obligados a ser los mismos. El alcance de las variables temporales de un método es local, o sea sólo en ese método. Por ejemplo, el método nombre: podría también implementarse de la siguiente manera:

nombre: nombreAlumno nombre := nombreAlumno

El método nombre:direccion: podría elegir directamente asignar el valor a las variables, en vez de usar lo métodos nombre: y direccion:. Esto se implementaría de esta forma:

nombre: unNombre direccion: unaDireccion nombre := unNombre. direccion := unaDireccion

Sin embargo es mejor centralizar la asignación de variables dentro de un método simple. Lo mismo se aplica a la obtención de los contenidos de una variable.

Página 18

Page 19: Manual de Smalltalk

Manual de Smalltalk - Ing. Lucas Spigariol

Capítulo 3:

Instrucciones Smalltalk

Presentación sintética:

Existen varias reglas que gobiernan la sintaxis y gramática en que son escritas las instrucciones de Smalltalk. Una instrucción de Smalltalk, además de contener mensajes, puede contener una instrucción de asignación (determinar el contenido específico de una variable dada), o devolver una expresión.

La sintaxis de Smalltalk consiste de:

Instrucciones: consisten en una o más expresiones Smalltalk válidas.

Asignaciones: apunta la variable a la izquierda de := al valor de retorno de la instrucción de la derecha.

Comentarios: son cualquier agrupación de caracteres encerrados entre dobles comillas.

Variables temporales están declaradas al comienzo de un método justo después de la definición de interfase del método

Bloques: permiten que el código sea pasado como argumento en un mensaje y ejecutado posteriormente en otro método.

Instrucciones

En Smalltalk, el código ejecutable está formado por instrucciones. Cada instrucción tendrá una o más expresiones Smalltalk. Una expresión válida de Smalltalk puede ser cualquiera de las siguientes:

Un nombre de variable Una literal Un envío de mensajes

Cada instrucción se separa por un punto, excepto la última instrucción. Si una instrucción tiene más de una expresión, la instrucción se ejecuta de acuerdo al orden de ejecución de los mensajes discutido en el capítulo anterior

Cuando Smalltalk procesa cada mensaje, la instrucción en el mensaje se reemplaza por un valor retornado, que es el resultado de ejecutar

Página 19

Page 20: Manual de Smalltalk

Manual de Smalltalk - Ing. Lucas Spigariol

el mensaje. El siguiente es un ejemplo del método nombre:direccion: de la clase Alumno:

nombre: unNombre direccion: unaDireccion self nombre: unNombre. self direccion: unaDireccion

Note que la primera línea es la definición de la interfase de un método, y que no termina con un punto (.). La línea final no necesita un punto final, porque es el final del método.

El punto es opcional para la última instrucción de un método. Smalltalk separa las instrucciones ejecutables por medio del punto. Como resultado, múltiples instrucciones pueden aparecen en una sola línea; o una sola instrucción puede aparecer en muchas líneas. El ejemplo anterior puede ser escrito de la siguiente manera:

nombre: unNombre direccion: unaDireccion self nombre: unNombre. self direccion: unaDireccion

Para que el código sea más fácil de leer, no se suele tener más de una instrucción en una sola línea. Las líneas en blanco son ignoradas por Smalltalk.

Asignación

Una asignación cambia el valor del objeto al que apunta una variable. En Smalltalk, una variable apunta a un objeto en vez de guardarlo. Se dice que una variable contiene al identificador del objeto.

La sintaxis para una instrucción de asignación es:

variable := instrucción

donde la variable puede ser un nombre dentro del alcance del método, y la instrucción puede ser cualquier instrucción válida de Smalltalk.

Por ejemplo:

x := 7. k := 'algunos caracteres'. unaVariable := j * k.

Devolución de Valores

Página 20

Page 21: Manual de Smalltalk

Manual de Smalltalk - Ing. Lucas Spigariol

En Smalltalk, un mensaje siempre devolverá un valor. La devolución por defecto, es el receptor del objeto. Un método puede anular su valor de retorno por defecto, colocando un símbolo de intercalación (^) adelante de una instrucción. Cuando se encuentra un ^, el método finaliza la ejecución y devuelve el valor de la instrucción que le sigue al símbolo de retorno ^.

Por ejemplo:

^instrucción

Se retorna el resultado de la instrucción, donde instrucción puede ser cualquier instrucción válida. Una expresión de retorno aparece normalmente adelante de la última instrucción de un método, o adelante de una instrucción que se ejecuta como parte de una instrucción de control. El siguiente ejemplo es una práctica importante, porque pone de manifiesto que la instrucción de retorno finaliza la ejecución del método en la que se encuentra.

Por Ejemplo:

y := y + 7. ^y "devuelve el valor de y"

La instrucción también puede ser escrita como:

^y := y + 7. "devuelve el valor de y"

Para devolver el valor de y + 7 sin modificar el valor de y:

^y + 7 "devuelve el valor de y + 7, pero no modifica el valor de y"

Devolviendo un valor desde una instrucción condicional

(a < b) ifTrue: [^a] ifFalse:[^b]

Este ejemplo contiene más de una instrucción de retorno. Este código devuelve el valor de a si a es mayor que b, caso contrario devuelve el valor de b.

En la instrucción ^a, la expresión es la variable a y el valor retornado de la expresión es el valor de a. El valor de una instrucción siempre es equivalente a la última expresión ejecutada en la instrucción.

Para las instrucciones que poseen más de un mensaje, el valor de retorno equivale al valor del último mensaje ejecutado.

Por ejemplo:

Página 21

Page 22: Manual de Smalltalk

Manual de Smalltalk - Ing. Lucas Spigariol

^Alumno new nombre: unaPersona nombre

Las instrucciones del ejemplo son evaluadas en el siguiente orden:

1º El mensaje new se envía a la clase Alumno

2º El mensaje nombre se envía al objeto apuntado por la variable unaPersona

3º El mensaje nombre: se envía al resultado del mensaje new

El valor de la instrucción será el valor del mensaje nombre:, porque es el último mensaje en ejecutarse. El mensaje nombre: no especifica un valor de retorno, por lo que devuelve el valor por defecto. ¿Cuál es el valor por defecto? El valor por defecto siempre es self, que es el receptor del mensaje. Por lo tanto, en este ejemplo, el valor de retorno es la instancia Alumno creada por el mensaje new (el receptor del mensaje nombre:).

Comentarios

En Smalltalk, los comentarios se encierran entre comillas dobles, tal como:

"esto es un comentario en Smalltalk"

Es una convención aceptada el tener comentarios al principio de un método, para explicar su comportamiento, incluyendo su valor de retorno.

Por ejemplo:

nombre "Devuelve el nombre del alumno receptor." ^nombre

Cuando Smalltalk ejecuta un método, ignora todos los comentarios. Esto significa que un comentario puede aparecer en cualquier lado, siempre y cuando sea colocado entre dobles comillas.

Variables Temporales

Las variables temporales están definidas en la definición de interfase de un método.

Página 22

Page 23: Manual de Smalltalk

Manual de Smalltalk - Ing. Lucas Spigariol

Por ejemplo:

nombre: unNombre direccion: unaDireccion

En la instrucción hay definidas dos variables temporales: unNombre y unaDireccion. Estas variables temporales contienen los argumentos pasados en el mensaje nombre:direccion:.

Un método puede tener más variables temporales, listándolas entre barras verticales ('|' pipeline),

Por ejemplo:

| nuevoNombre nuevaDireccion |

Esta instrucción no termina con un punto.

El nombre de una variable temporal comienza con una letra en minúscula, y debe ser único dentro del método. Esto significa que no puede duplicar el nombre de una variable de instancia, ni duplicar el de una variable temporal definida en una interfase, así como tampoco puede duplicar el nombre de una variable temporal cualquiera.

Estructura Básica de un Método

El siguiente es un ejemplo de un método:

unMetodoEjemplo: algunaEntrada "Esto es un ejemplo de un método." | nuevoValor | nuevoValor := algunaEntrada * 2. ^nuevoValor

Este método no tiene mayor significado que el de ilustrar el aspecto básico de un método.

La primera línea define la interfase del método, así como también al nombre del método. Este método es un método de palabra clave con un argumento. El nombre del método es unMétodoEjemplo y la variable temporal es algunaEntrada.

La segunda línea es un comentario describiendo lo que hace el método.

La tercera línea es una declaración de una variable temporal adicional llamada nuevoValor. Esta variable temporal es local sólo dentro de este método.

La cuarta y la quinta línea contienen la lógica del método. Un punto es opcional para la última línea de un método. La última línea contiene una expresión de retorno, que no será necesaria

Página 23

Page 24: Manual de Smalltalk

Manual de Smalltalk - Ing. Lucas Spigariol

a menos que se explicite un valor de retorno diferente al receptor del mensaje.

Sin embargo este método no contiene un código eficiente. Define una variable que mantiene el resultado de la multiplicación, y luego usa esa variable temporal sólo en la instrucción de retorno. De modo que el método puede simplificarse así:

unMétodoEjemplo: algunaEntrada "Esto es un ejemplo de un método." ^algunaEntrada * 5

La expresión de retorno primero procesa todas las instrucciones que aparecen a su derecha y luego devuelve el valor de la última expresión ejecutada. En este ejemplo el resultado del mensaje de multiplicación es el valor de retorno.

Bloques

Los bloques son corchetes que contienen ninguna o muchas expresiones, y un código que realiza iteraciones o ejecuciones condicionales. Por ejemplo, un bloque de código es utilizado para especificar qué ejecutar como resultado de una condición verdadera o falsa:

ifTrue: [x := 2] ifFalse: [x := 5]

Un bloque puede pensarse como un mini-método dentro de un método. Las siguientes reglas se aplican a los bloques:

Un bloque puede contener cualquier número de instrucciones válidas ejecutables, o cualquier número de comentarios.

Cada instrucción debe terminar con un punto, excepto cuando se definen las variables temporales, y en la última instrucción del bloque, donde el punto es opcional.

Un bloque tiene acceso a las mismas variables que el método al que pertenece.

Como un bloque es parte de un método no posee una definición de interfase de método. El bloque en la siguiente instrucción:

ifTrue: [x := 2]

es llamado bloque de cero-argumento; no puede aceptar ningún argumento. Sin embargo es posible definir un bloque que pueda tomar argumentos, como el siguiente:

Página 24

Page 25: Manual de Smalltalk

Manual de Smalltalk - Ing. Lucas Spigariol

[:variable1 | código] [:variable1 :variable2 | código]

donde variable1 y variable2 son variables temporales y son válidas sólo dentro del alcance del bloque. El nombre de la variable es precedido por dos puntos ':'.

Por ejemplo:

[:unNumero | x * unNumero]

La variable unNumero está definida dentro del bloque. Esta instrucción multiplica una variable llamada x por el argumento pasado en el bloque. La variable x debe estar dentro del alcance del método en donde se encuentra el bloque.

En el próximo capítulo serán discutidos en más detalle los bloques, y los mensajes que requieren bloques como argumento.

Mensajes en cascada

Algunas veces es necesario enviar a un objeto varios mensajes consecutivos. Como ejemplo, revea el siguiente código:

nombre: unNombre direccion: unaDireccion telefono: unTelefono "Determina el nombre, dirección y teléfono de una instancia Alumno." self nombre: unNombre. self direccion: unaDireccion. self telefono: unTelefono

Self es el receptor de los mensajes para todas las instrucciones del método. Para ejecutar los mensajes correctamente, necesitan aparecer en instrucciones separadas. Se examinará qué ocurre cuando self es seguido por todos estos mensajes de palabra clave sin ninguna separación:

self nombre: unNombre direccion: unaDireccion telefono: unTelefono.

Dado que Smalltalk permite el agrupamiento de todas las palabras clave en una sola expresión, el mensaje nombre:direccion:telefono sería enviado al receptor como una expresión válida. Sin embargo esto provocará un número infinito de llamadas recursivas (debe tener en cuenta que este nombre de mensaje es el mismo que el nombre del método en el que se encuentra esta expresión). Para evitar esto, cada palabra clave debe estar en una instrucción separada.

Si las tres instrucciones se combinan en una sola con self adelante de cada palabra clave, de la siguiente manera:

Página 25

Page 26: Manual de Smalltalk

Manual de Smalltalk - Ing. Lucas Spigariol

self nombre: unNombre self direccion: unaDireccion self telefono: unTelefono.

Smalltalk evalúa el segundo self en la instrucción como un mensaje enviado al objeto unNombre. Evalúa al último self como un mensaje enviado al objeto unaDireccion. Esto causa un error de ejecución, ya que self no es un mensaje soportado por ninguno de esos dos objetos.

Existe una forma de acortar el código que permite trabajar con instrucciones consecutivas. La primera instrucción se escribe de manera normal, pero todas las instrucciones sucesivas pueden omitir al objeto receptor. Cada instrucción termina con un punto y coma (;) en vez de con un punto (.), exceptuando a la última instrucción para la que el punto es opcional. El método del Ejemplo 3.3 puede se escrito de la siguiente forma:

nombre: unNombre direccion: unaDireccion telefono: unTelefono "Determina el nombre, dirección y teléfono de una instancia Alumno."self nombre: unNombre;direccion: unaDireccion;telefono: unTelefono

La primera instrucción se escribe de manera normal, excepto que termina con un punto y coma. El objeto receptor del último mensaje en esta secuencia, se vuelve el objeto receptor del primer mensaje en la siguiente instrucción.

Página 26

Page 27: Manual de Smalltalk

Manual de Smalltalk - Ing. Lucas Spigariol

Capítulo 4:

Operaciones con Datos

Presentación sintética:

¿Cómo hace Smalltalk para tratar con datos, comparaciones lógicas, iteración y otras funciones condicionales? “Todo en Smalltalk es un objeto”, es por esto que Smalltalk implementa todos los tipos de datos como clases de Smalltalk, y las operaciones sobre datos como los métodos de estas clases.

A diferencia de los lenguajes procedurales donde los tipos de datos y operaciones son definidos como parte de la sintaxis del lenguaje, Smalltalk no conoce los tipos de datos o las operaciones sobre datos. Los nuevos datos pueden ser creados como instancias de una clase. Las operaciones sobre datos se realizan enviando un mensaje al objeto.

Un literal puede ser utilizado explícitamente para definir datos. Un literal puede ser un número (Number), una cadena (String), un carácter (Character), un símbolo (Symbol), o un vector (Array) de literales.

Las operaciones sobre datos, incluyendo las comparaciones lógicas, las operaciones aritméticas, las operaciones lógicas usando "and" y "or", los condicionales lógicos, y las iteraciones, son implementadas como métodos en sus respectivas clases.

Todas las variables inicialmente apuntan al objeto nil. Este valor es una instancia de una clase llamada UndefinedObject.

Literales

Smalltalk provee soporte para los literales como instancias de cinco clases: String (cadena), Number (número), Character (carácter), Symbol (símbolo) y Array (vector).

Las subclases de Number: Integer (entero), Float (real), y Fraction (fracción) son parte de los literales también.

Página 27

Page 28: Manual de Smalltalk

Manual de Smalltalk - Ing. Lucas Spigariol

Number

Un number (número) puede ser uno cualquiera de los siguientes:

Un integer (entero) de cualquier longitud Una fraction (fracción) Un número de floating point (punto flotante)

123 "un entero" -234 "un entero negativo" 3/4 "una fracción" -1/7 "una fracción negativa" 4.564 "un número de punto flotante" -2.34e10 "un número de punto flotante negativo" .23 "ERROR Un número no puede comenzar con un punto decimal" 59. "ERROR Un número no puede terminar con un punto decimal" 2.4e.7 "ERROR El exponente debe ser un entero"

Character

Un character (carácter) es cualquier carácter ASCII precedido por el signo $, tal como $G o $@. La siguiente instrucción determina si el primer carácter de una cadena es igual a 'Y' mayúscula:

unaCadena first = $Y

String

Un string (cadena) es cualquier secuencia de caracteres encerrados entre comillas simples. Por ejemplo:

'Esto es una cadena.' 'Las cadenas pueden contener esto %@#^|\' nuevoAlumno nombre: 'Pedro' "Determina el argumento del mensaje nombre:

como una cadena."

Symbol

Un symbol (símbolo) es un identificador, selector binario, o un selector de palabra clave, precedido por un signo numeral, #. Todos los símbolos son únicos.

#nombre "un identificador" #+ "un selector binario" #at:put: "un selector de palabra clave"

Página 28

Page 29: Manual de Smalltalk

Manual de Smalltalk - Ing. Lucas Spigariol

Array

Un array (vector) es una estructura de datos cuyos elementos pueden ser cualquier objeto válido. Un vector literal es una secuencia indexada de otros literales. Un vector se caracteriza por estar encerrado entre paréntesis y precedido por un signo numeral (#). Por ejemplo:

#('uno' 'dos' 'tres' 'cuatro') "Produce un vector de cuatro cadenas" #(1 2 3 4) "Produce un vector con cuatro enteros" #(1 'dos' $Y) "Produce un vector con un entero, una cadena, y un caracter"

Operaciones Aritméticas

Una instrucción que realiza una operación aritmética en Smalltalk tiene la siguiente forma:

número operación número

donde una operación puede ser una de las siguientes: + "suma" - "resta" * "multiplicación" / "división" // "división entera (cociente)" \\ "resto de una división"

Los siguientes son algunos ejemplos de operaciones aritméticas:

3 + 4. "devuelve 7" 9 // 4. "devuelve 2" 9 \\ 4. "devuelve 1"

| x y | x := 2. y := 6. x * y "devuelve 12"

Nil

En Smalltalk, nil es un objeto que significa "nada". Inicialmente todas las variables apuntan a nil. Cualquier variable puede ser apuntada a nil durante la ejecución, con una instrucción como la siguiente:

UnaVariable := nil.

Página 29

Page 30: Manual de Smalltalk

Manual de Smalltalk - Ing. Lucas Spigariol

Nil también puede usarse como un valor de retorno para indicar que una operación no fue exitosa. Por ejemplo, la siguiente lógica devuelve nil si un argumento es no positivo, caso contrario devuelve el resultado de la operación aritmética:

raise: unNumero toPower: unaPotencia "Raise (eleva) unNumero a toPower (a la potencia) especificada por unaPotencia. Devuelve nil si unaPotencia es no positiva. Caso contrario, devuelve el resultado." unaPotencia < 0

ifFalse: [^nil]. ^aNumber raisedTo: aPower

True y false

En Smalltalk los valores true y false son provistos por las clases True y False, respectivamente y representan los valores booleanos utilizados en toda expresión condicional y comparación lógica.

Comparaciones Lógicas

Una instrucción de comparación tiene el siguiente formato:

valor comparación valor

donde valor puede ser cualquier expresión que resulte en un valor que pueda ser comparado, tal como números, cadenas, caracteres, y símbolos; y comparación puede ser cualquier operación válida de comparación. Algunos ejemplos son: > "mayor que" < "menor que" = "igual en valor" ~= "desigual en valor" >= "mayor o igual que" <= "menor o igual que" == "el mismo objeto que"

Las comparaciones lógicas devuelven un valor que puede ser true (verdadero) o false (falso), que son instancias de las clases True y False, respectivamente.

Los siguientes son algunos ejemplos de comparaciones lógicas:

3 > 8 "devuelve false" $e <= $f "devuelve true"

| i j | i := 3. j := 7.

Página 30

Page 31: Manual de Smalltalk

Manual de Smalltalk - Ing. Lucas Spigariol

i == j "devuelve false"

La comparación "==", en el último ejemplo, compara si dos objetos son el mismo objeto, en vez de comparar si son iguales en valor.

"y" Lógico y "o" Lógico

En Smalltalk, las expresiones booleanas pueden ser combinadas en un resultado, usando la operación o, o la operación y. Estas dos funciones pueden ser utilizadas como mensajes binarios o mensajes de palabra clave.

El mensaje binario para el y lógico es &, y para el o lógico es |. Por ejemplo:

(a > 0) & (b < 0) "Devuelve true si a es positivo y b es negativo. Caso contrario devuelve false."

(a > 0) | (b < 0) "Devuelve true si a es positivo y/o b es negativo. Caso contrario devuelve false."

Una sentencia puede contener un número ilimitado de mensajes binarios. Por ejemplo:

| x y z | x := 3. y := 5. z := 7. (x > 0) & (y < 0) | (x > y) & (y = z)

El mensaje de palabra clave para y lógico es and:, y para o lógico es or:. El formato para estos mensajes es:

booleano and: [código] booleano or: [código]

El booleano es cualquier expresión cuyo valor resulte true o false. El bloque de código encerrado entre corchetes debe devolver un valor de true o false. Los métodos and: y or: combinan los dos valores booleanos y devuelve el resultado correspondiente.

Existe una diferencia entre los mensajes binarios & y |, y los mensajes de palabra clave and: y or:, respectivamente. Los mensajes de palabra clave son considerados caminos cortos porque utilizan evaluación diferida. El código en el bloque no es evaluado hasta que el valor del receptor booleano no es determinado como true o false.

En el caso del mensaje and:, si el receptor evalúa false, entonces el código del bloque no se ejecuta, ya que en una operación and con un false siempre es false.

Página 31

Page 32: Manual de Smalltalk

Manual de Smalltalk - Ing. Lucas Spigariol

En el caso del mensaje or:, si el receptor evalúa true, entonces el código del bloque no se ejecuta, ya que en una operación or con un true siempre es true.

El siguiente es un ejemplo utilizando mensajes de palabra clave:

| x y z | x := 3. y := 5. z := 7. (((x > 0) and: [y < 0]) or: [x > y]) and: [y = z]

Not

El mensaje unario not provee la función not. Este mensaje invierte un valor booleano (true se vuelve false, o false se vuelve true). El formato es:

booleano not

El siguiente es un ejemplo:

(5 > 1) not "El valor de retorno es false."

Lógica Condicional

La lógica condicional permite la ejecución del código dependiendo de un valor booleano. Existen varios mensajes de palabra clave que proveen esta función, por ejemplo:

booleano ifTrue: [código] ifFalse: [código].

donde booleano es cualquier expresión que resulte true o false. La expresión [código] puede ser cualquier bloque de cero-argumentos.

El mensaje de palabra clave ifTrue:ifFalse ejecuta un bloque diferente dependiendo del valor del booleano. Por ejemplo:

| x y nuevoValor | x := 1. y := 2. (x > y) ifTrue: [nuevoValor := x] ifFalse: [nuevoValor := y].

^nuevoValor

Este ejemplo determina el valor de la variable nuevoValor al valor del mayor entre x o y, en este caso y, y devuelve el valor en nuevoValor.

Página 32

Page 33: Manual de Smalltalk

Manual de Smalltalk - Ing. Lucas Spigariol

Iteraciones

Smalltalk soporta cuatro tipos tradicionales de iteraciones. Ellos son:

Hacer algo n número de veces Hacer algo hasta que se encuentre con una condición false Hacer algo hasta que se encuentre con una condición true Hacer algo usando un índice, comenzando con un valor inicial, y

finalizando en un valor final.

Los cuatro mensajes de palabra clave que proveen estas funciones son: timesRepeat:, whileTrue:, whileFalse:, y to:do:.

timesRepeat:

El mensaje timesRepeat: ejecuta un bloque de código un número específico de veces. El formato del mensaje es:

número timesRepeat: [código]

donde número puede ser cualquier expresión que resulte en un entero, y código es un bloque de código de cero-argumento. El siguiente es un ejemplo:

"Agrega 1 a la variable x tres veces." | x | x := 2. 3 timesRepeat: [x := x + 1]. ^x

El resultado es 5.

whileTrue: y whileFalse:

Estos dos mensajes realizan la misma operación, excepto que uno se ejecuta por true y el otro por false. El formato del mensaje es:

[booleano] whileFalse: [código] [booleano] whileTrue: [código]

Un booleano puede ser cualquier expresión que resulte en un valor de true o false; debe estar encerrado en un bloque. La expresión [código] es un bloque de código de cero-argumento. Por ejemplo, ambos ejemplos incrementan y de a 1 hasta que es mayor a x.

Página 33

Page 34: Manual de Smalltalk

Manual de Smalltalk - Ing. Lucas Spigariol

"Itera mientras x es menor que y" | x y | x := 5. y := 0. [x < y] whileFalse: [y := y + 1]. ^y

"Itera hasta que y es mayor than x" | x y | x := 5. y := 0. [y <= x] whileTrue: [y := y + 1]. ^y

to:do:

El mensaje to:do: ejecuta un bloque múltiples veces, basado en un valor inicial y un valor final. El formato del mensaje es:

número1 to: número2 do: [:var | código].

donde número1 y número2 pueden ser cualquier expresión que resulte en un número, y [:var | código] es un bloque de código de un-argumento. El bloque se ejecuta para cada número perteneciente al rango entre número1 y número2, inclusive. (Este formato es utilizado generalmente con enteros, que varían en el rango de a 1 a la vez.). El argumento del bloque de un-argumento equivale al valor actual en el rango.

"Ejecuta este bloque 3 veces con i referenciado a cada valor entre el rango de 1 a 3. Al final x valdrá 6." | x | x := 0. 1 to: 3 do: [:i | x := x + i]. ^x

Página 34

Page 35: Manual de Smalltalk

Manual de Smalltalk - Ing. Lucas Spigariol

Capítulo 5:

Herencia

Presentación sintética:

La herencia es una característica de Smalltalk que habilita a una clase a tener el mismo comportamiento que otra clase, y luego cambiar ese comportamiento para ofrecer un comportamiento único. La herencia es especialmente importante en cuanto que dota al lenguaje Smalltalk de las características de reusabilidad y extensibilidad.

Las clases que heredan el comportamiento de otras clases se llaman subclases.

Las clases cuyo comportamiento es heredado por otras clases se llaman superclases.

Una subclase puede agregar nuevos métodos a su comportamiento o reemplazar (redefinición) los métodos heredados.

Una subclase puede agregar nuevas variables de instancia o de clase a su definición.

Una variable de clase existe sólo una vez en una clase y sus subclases, y es compartida por todas ellas.

Una clase abstracta ofrece un comportamiento común para todas sus subclases, pero esto no significa que pueda tener instancias propias.

El nombre super actúa de manera similar al self en cuanto que representa al objeto receptor del, pero causa que la búsqueda del método a ejecutar comience por la superclase del objeto receptor.

¿Qué es la Herencia?

Un ejemplo de herencia es cuando alguien tiene un programa y desea que su programa realice más de una función. La herencia permite que el usuario extienda el programa existente para que realice la función que se necesite. El siguiente diagrama muestra un ejemplo de herencia:

Página 35

Page 36: Manual de Smalltalk

Manual de Smalltalk - Ing. Lucas Spigariol

La herencia involucra superclases y subclases. Estas clases son similares en su jerarquía, a las ideas de clase, género, y la familia de clasificaciones en el mundo animal. La jerarquía de herencias es ilimitada. Esto significa que las subclases pueden tener subclases que también tienen subclases. La clase Persona que se muestra en el siguiente gráfico tiene variables de instancia llamadas nombre, direccion, y telefono. La subclase Cliente tiene las mismas variables de instancia. La clase Persona soporta los mensajes nombre, direccion, telefono, nombre:, direccion:, y telefono:. La subclase Cliente también soporta estos mensajes.

En la herencia, la subclase siempre toma el comportamiento y la estructura interna de las superclases superior a ella.

Página 36

Page 37: Manual de Smalltalk

Manual de Smalltalk - Ing. Lucas Spigariol

Herencia de Métodos

La herencia de métodos es útil para permitir a una clase modificar su comportamiento respecto de su superclase. Esto puede ser hecho agregando nuevos métodos, o redefiniendo los métodos heredados.

Agregando Métodos

Se puede agregar métodos de manera muy simple, incorporándolos, ya sean de instancia o de clase, en la definición de la clase. Todo objeto de la subclase soporta los métodos de su superclase, más los nuevos métodos.

En el gráfico anterior, la definición de la clase Cliente también desearía gestionar los pedidos de los clientes. Entonces, la definición de la clase deseará agregar: pedidosCliente, pedidosCliente:, y agregarPedidoCliente:. La definición de la clase Cliente puede ahora soportar todos los mensajes o métodos de la clase Persona y los nuevos tres mensajes.

Página 37

Page 38: Manual de Smalltalk

Manual de Smalltalk - Ing. Lucas Spigariol

Redefinición de Métodos

La redefinición de un método heredado es otra herramienta que los usuarios tienen para proveer de un comportamiento único a una clase. Si un objeto recibe un mensaje que existe en la definición de la clase, el objeto busca en la jerarquía hasta que encuentra el método con ese nombre. Los métodos heredados no pueden eliminarse.

La figura muestra cómo Smalltalk trabaja con la jerarquía cuando está buscando un método para un mensaje.

Enviando Métodos a Instancias

En la jerarquía, una subclase hereda los métodos de su superclase. La instancia de una clase puede recibir un mensaje para buscar un método que no es soportado por la clase. La instancia de la clase busca en sí misma para saber si el método existe en ella. Si no, la búsqueda se pasa a la superclase de la subclase, si tampoco lo encuentra busca en la superclase de su superclase y así continúa hasta llegar a Object, si no lo encuentra tampoco en Object envía un mensaje de error. Si el método es encontrado, entonces se hereda en la instancia de la subclase.

Herencia de Variables

La jerarquía del lenguaje Smalltalk, ha sido diseñada para que las subclases hereden las variables de sus superclases. Las subclases también pueden poseer variables propias. Las variables de instancia se agregan a la clase colocándolas en la definición de clase.

Las variables de instancia están definidas en la definición de la clase. Los datos de la instancia se mantienen en un área de datos creada por Smalltalk.

Página 38

Page 39: Manual de Smalltalk

Manual de Smalltalk - Ing. Lucas Spigariol

La variable Cliente tiene las variables de instancia: nombre, direccion, telefono, y pedidosCliente. Estas variables incluyen las variables de instancia heredadas de Persona. Cada instancia posee su propia copia de las variables de instancia, de esta forma hace a las variables de instancia propias de la instancia. Entonces, el nombre de la variable debe comenzar con una letra minúscula.

Variables de Clase

Una variable de clase es una variable que es compartida por todos los objetos de la clase. Sólo existe una copia de la variable de clase en la jerarquía local de clases. Todos los objetos de la clase referencian a esta única copia de la variable.

Las variables de clase también permiten compartir la información a través de todas las subclases de la clase en que fueron declaradas.

Tienen las mismas convenciones de nombramiento que las variables de instancia, excepto que la primera letra de una variable de clase debe comenzar con mayúscula.

Relación entre métodos y variables de clase

Los métodos de instancia y los métodos de clase pueden referirse a las variables de clase, pero sólo los métodos de instancia pueden referirse a las variables de instancia. El siguiente diagrama muestra este hecho:

Página 39

Page 40: Manual de Smalltalk

Manual de Smalltalk - Ing. Lucas Spigariol

Variables de Instancia de Clase

Las variables de instancia de clase son como las variables de clase, excepto que cada subclase tiene su propia copia. Dado que es una variable privada, las variables de instancia de clase deben comenzar con minúscula. Las variables de instancia de clase soportan el comportamiento de herencia, teniendo cada clase su propio estado de la variable.

Clases Abstractas

Las clases abstractas proveen de un comportamiento a sus subclases, pero nunca tendrán sus propias instancias. La siguiente figura muestra con un recuadro más claro las clases abstractas de un supuesto árbol de jerarquías de Smalltalk.

Super y Self

El uso de super provoca que la búsqueda del método comience en la superclase del objeto receptor. Super es la única forma en que la clase pueda agregar comportamiento a los métodos sin tener que reemplazarlos. Cuando super es encontrado en la ejecución de un programa, Smalltalk busca el método en la superclase del receptor.

Super también es usado para crear variables de instancia por cada nueva instancia. Esto se hace por medio de un método de inicialización por cada clase. Un ejemplo para crear una nueva instancia de una clase es:

Private Class Methods new

Página 40

Page 41: Manual de Smalltalk

Manual de Smalltalk - Ing. Lucas Spigariol

^super new inicializar

Self hace que la búsqueda del método comience en el mismo objeto receptor. Cuando self es encontrado en la ejecución de un programa, Smalltalk busca el método en el receptor. Un ejemplo del uso del comando self es: self calcular que significa enviar el mensaje calcular a self.

Página 41

Page 42: Manual de Smalltalk

Manual de Smalltalk - Ing. Lucas Spigariol

Capítulo 6:

Colecciones

Presentación sintética:

Una Bag (Bolsa) es una colección de tamaño variable, que guarda objetos en un orden al azar y que no es indexable.

Un Set (Conjunto) es idéntica a una Bolsa excepto en que no permite objetos duplicados.

Un Array (Vector o Arreglo) es una colección de tamaño fijo que es indexable.

Una OrderedCollection (Colección Organizada) es una colección de tamaño variable que es indexable.

Una SortedCollection (Colección Ordenada) es una colección de tamaño variable que guarda objetos en un orden específico por medio de un bloque de ordenamiento de dos argumentos.

Un String (Cadena) es similar a un vector excepto en que sólo contiene caracteres.

Un Symbol (Símbolo) es similar a una cadena excepto en que no permite objetos Symbol duplicados con el mismo valor.

Un Dictionary (Diccionario) administra pares clave/valor y permite acceder por clave a los objetos que contiene.

Las Colecciones tienen varios mensajes que soportan la administración de una colección. Esto incluye preguntar por su tamaño (size), agregar (add) objetos a una colección, eliminar (remove) ítems, e iterar (do) a través de una colección.

¿Qué es una Colección?

Una colección es una estructura de datos que referencia a un conjunto de objetos. Son objetos que contienen y manejan grupos de objetos

Página 42

Page 43: Manual de Smalltalk

Manual de Smalltalk - Ing. Lucas Spigariol

Smalltalk posee un número de diferentes tipos de colecciones. El siguiente diagrama ilustra la jerarquía de clases de estas clases de colecciones:

A la mayoría de las colecciones no les importa que clase de objeto esté manejando. Si se quisiera, cada elemento en una colección podría contener un objeto diferente de una clase diferente. Algunas colecciones son específicas respecto del tipo de objeto que manejan. Por ejemplo, la clase String es una colección que debe contener objetos del tipo Character (carácter).

Las colecciones varían en las capacidades que ofrecen. Algunas colecciones pueden crecer y decrecer en tamaño y son útiles para grupos de objetos que requieren de este comportamiento. Por ejemplo, si cada instancia de Cliente estuviera en una lista, el agregado o eliminación de clientes podría hacer que esta lista incremente o decremente su número. Para implementar esta lista, se necesitaría una colección de tamaño variable que posea este comportamiento. Con una colección de tamaño variable, su tamaño inicial puede ser especificado, o por defecto, ser utilizado algún valor apropiado. Otras colecciones no pueden cambiar su tamaño y, como resultado, suelen tener un esquema de manejo más eficiente. Las colecciones de tamaño fijo son apropiadas cuando el número de elementos en un grupo es conocido y estable.

Página 43

Page 44: Manual de Smalltalk

Manual de Smalltalk - Ing. Lucas Spigariol

Una colección organizada tiene una organización sobre sus elementos. Esta organización puede ser un índice simple, como en un Array (vector), o una clave como en un Dictionary (diccionario), o impuesta por algún orden interno como en una SortedCollection (colección ordenada).

La indexación permite referirse a un elemento en un lugar fijo. Por ejemplo, en un vector de tres cadenas: #('rojo' 'blanco' 'azul'), se puede solicitar el elemento en el índice (lugar) 1. Todos los índices comienzan en 1 y terminan en el tamaño de la colección. Las colecciones indexadas siempre están organizadas y no cambian en forma arbitraria el orden de los elementos de la colección. Un objeto permanece en el lugar que le fue asignado, hasta que sea explícitamente movido de lugar.

Algunas colecciones tienen características adicionales, como por ejemplo el self, que no permiten elementos duplicados dentro de la colección.

Colecciones Comunes

Smalltalk tiene varias colecciones comunes. La siguiente tabla muestra estas colecciones y sus comportamientos:

COLECCIONES Indexación Tamaño variable

Duplicados

Orden Contenidos

Bag N S S N Cualquier objeto, pero no nil

Set N S N N Cualquier objeto, pero no nil

Array S N S N Cualquier Objeto

OrderedCollection S S S N Cualquier objeto

SortedCollection S S S S Cualquier objeto

String S N S N Caracteres

Symbol S N N N Caracteres

Dictionary N S N N Clave + Cualquier objeto

S = Comportamiento soportado, N = Comportamiento no soportado

Las Clases de Colecciones tiene varios comportamientos similares, ellos son:

representan un grupo de objetos llamados elementos proveen un estructura de datos básica para la programación

Página 44

Page 45: Manual de Smalltalk

Manual de Smalltalk - Ing. Lucas Spigariol

reemplazan construcciones iterativas en los lenguajes tradicionales con los Mensajes a las Colecciones do:, detect:, select:, y collect:.

soportan cuatro categorías de mensajes que agregarán nuevos elementos, eliminarán elementos, determinarán las ocurrencias de los elementos, and enumerarán los elementos.

Bag (Bolsa)

Una Bag es una colección desorganizada de elementos que está preparada para una búsqueda eficiente. Una Bolsa actúa como un contenedor dentro del cual se pueden colocar y retirar cosas. Guardan sus elementos en un orden al azar y no pueden ser indexadas. Una Bolsa puede incrementar o decrementar su tamaño, y acepta elementos duplicados (puede contener el mismo objeto varias veces).

Como ejemplo, unaBag es utilizada para determinar el número de ocurrencias de cada elemento:

unaBag := #(1 2 3 3 3 3) asBag. unaBag size -> 6 unaBag occurrencesOf: 3 Salida: 4

Set (Conjunto)

Un Set es similar a una Bolsa excepto porque no permite objetos duplicados. Un Set ignora cualquier petición que pudiera agregar un elemento duplicado a la colección.

Por ejemplo, se podría decidir que es importante asegurarse que no hay clientes duplicados en la lista cada vez que un nuevo objeto cliente es agregado. En este caso un Conjunto es más apropiado que una Bolsa. Sin embargo, asegurarse que no hay duplicados agrega un costo cada vez que un objeto es añadido a la lista.

Por ejemplo, unSet es utilizado para determinar elementos únicos:

unSet := #(1 2 3 3 3 3) asSet. unSet size -> 3 unSet occurrencesOf: 3 Salida: 1

Array (Vector o Arreglo)

Página 45

Page 46: Manual de Smalltalk

Manual de Smalltalk - Ing. Lucas Spigariol

Un Array es una colección, de tamaño fijo, de elementos que pueden ser indexados por claves de números enteros que comienzan en 1 y se incrementan. Un Vector no puede crecer o disminuir. Los elementos de un Vector puede ser cualquier objeto, los objetos duplicados están permitidos, y los elementos se guardan según la posición.

Un Vector es útil cuando se conoce el tamaño de la colección y ese tamaño cambia raramente. Por ejemplo, asumamos que se está diseñando una aplicación para administrar habitaciones en un edificio. El número de habitaciones es fijo y se desea una manera rápida de indexar cada habitación para chequearlas por información, como ocupante o número de teléfono. Un Vector es una buena elección para esta situación.

Por ejemplo, unArray es un vector de 3 posiciones con 'hola' en la primera posición. Este ejemplo también demuestra la habilidad de indexación de unArray:

unArray := Array new: 3 unArray at: 1 put: 'hola' unArray at: 1 Salida: 'hola' unArray at: 3 Salida: nil

OrderedCollection (Colección Organizada)

Una OrderedCollection ofrece el protocolo más completo de cualquiera de las clases de colecciones, y es consecuentemente el "caballo de batalla" más utilizado por los programadores. Una Colección Organizada puede ser indexada por una clave de números enteros que comienzan en 1 y crecen. Los elementos de una Colección Organizada pueden ser objetos de cualquier clase. Una Colección Organizada también permite objetos duplicados y guarda los elementos en un orden al azar.

Esta colección es principalmente utilizada para listas de tamaño variable que requieren de un control sobre la ubicación de los elementos de la colección. Por ejemplo, una Colección Organizada es usualmente utilizada en las interfaces de usuario para mantener la información visible en una caja de listas. Esto permite que la información sea agregada o eliminada de la lista. El soporte de indexación es útil cuando el usuario selecciona un elemento en particular de la Colección Organizada.

Página 46

Page 47: Manual de Smalltalk

Manual de Smalltalk - Ing. Lucas Spigariol

SortedCollection (Colección Ordenada)

Una SortedCollection guarda objetos en el orden especificado por un bloque de código llamado sortBlock. El bloque sortBlock es un bloque de dos argumentos que indica el orden en que los dos argumentos debieran ser almacenados en la colección respecto uno del otro. La colección guarda el primer argumento adelante del segundo argumento en la colección cuando la evaluación del bloque sortBlock es verdadera (true). El bloque sortBlock puede contener múltiples sentencias, pero debe retornar un valor de verdad: true o false.

Por ejemplo, el siguiente bloque compara el objeto referenciado por la variable a con el objeto referenciado por la variable b:

[:a :b | a <= b] "devuelve true cuando a es menor o igual a b"

El bloque devuelve el valor true si el primer objeto es menor o igual que el segundo objeto. Es bloque hace que la colección guarde sus elementos en orden ascendente. Este es el bloque de ordenamiento por omisión que utiliza la clase SortedCollection.

Esta colección utiliza el bloque sortBlock cada vez que un elemento es agregado a la colección. El primer argumento en el bloque sortBlock siempre apunta al nuevo objeto y el segundo argumento apunta a un objeto existente. La colección ejecuta el bloque sortBlock en forma iterativa y secuencial recorriendo todos los elementos existentes en la colección, hasta que el bloque devuelva true, o hasta que no haya más elementos en la colección, en cuyo caso el nuevo elemento pasa a ser el último en el orden de la lista.

El método para escribir un nuevo bloque sortBlock es:

#(4 3 5 2 1) asSortedCollection: [:a :b | a >= b] #('uno' 'dos' 'tres') asSortedCollection: [ :x :y | x size >= y size]

Una Colección Ordenada es una buena elección para mantener una lista de clientes ordenada por nombre. Sin embargo, esto agrega un significante costo adicional cada vez que un nuevo objeto es añadido a la colección, de manera que debe usarse prudentemente.

Mensajes a las Colecciones

Las colecciones tienen una variedad de mensajes para administrarse:

new

Página 47

Page 48: Manual de Smalltalk

Manual de Smalltalk - Ing. Lucas Spigariol

El mensaje new designa una colección con un tamaño por omisión, que varía dependiendo del tipo de la colección. Este mensaje devuelve la nueva colección. Por ejemplo, la siguiente sentencia designa unaBag con el siguiente mensaje:

|unaBag| unaBag := Bag new

Este mensaje puede ser inapropiado para colecciones de tamaño fijo dado que designa una colección vacía (sin elementos). Se debe recordar que las colecciones de tamaño fijo no pueden crecer.

new: unNúmero

El mensaje new: designa una colección con un tamaño específico dado por el argumento unNúmero. El mensaje devuelve la nueva colección.

Para una colección de tamaño fijo, el argumento especifica un número de elementos en la colección. Pruebe el siguiente ejemplo:

Array new: 10

Esta expresión designa un vector de 10 elementos. Un mensaje size enviado a esta colección devolverá el número 10. Pruebe el siguiente ejemplo:

(Array new: 10) size

with: unObjeto

Estos cuatro mensajes crean una colección para contener los objetos especificados:

with: unObjeto with: unObjeto1 with: unObjeto2 with: unObjeto1 with: unObjeto2 with: unObjeto3 with: unObjeto1 with: unObjeto2 with: unObjeto3 with:

unObjeto4

El tamaño de la colección es igual al número de palabras clave en el mensaje. Por ejemplo, el mensaje with: crea una colección con un elemento y coloca unObjeto en esa ubicación de la colección. El mensaje devuelve la nueva colección. Este mensaje es válido para todas las colecciones. Pruebe el siguiente ejemplo

Array with:'cadena 1' with:'cadena 2'. OrderedCollection with:1 with:2 with:3 with:4.

size

Página 48

Page 49: Manual de Smalltalk

Manual de Smalltalk - Ing. Lucas Spigariol

El mensaje size devuelve el número de elementos actualmente en la colección. Es soportado por todas las colecciones. Si la colección está vacía, su tamaño será cero. Este mensaje se encuentra en varios de los ejemplos anteriores.

do: unBloque

El mensaje do: es una iteración general que recorre cada elemento de la colección y ejecuta un bloque de código de un argumento, especificado por el argumento unBloque, con cada elemento de la colección como argumento de este bloque.

Por ejemplo, el siguiente código contará el número de vocales en la cadena 'ahora es el momento' y devolverá el valor 8. Pruebe el ejemplo:

"Cuenta el numero de vocales en una cadena." |vocales cadena| vocales := 0. cadena := 'ahora es el momento'. cadena do: [:letra | letra isVowel ifTrue: [ vocales := vocales + 1]] ^vocales

Sea otro ejemplo, donde se tiene una colección de números, se calcula la suma de todos los números de la colección, obteniéndose un resultado de 15. Pruebe el ejemplo:

"Calcula el total de la suma de los números en numeros." |numeros suma| numeros := #(1 2 3 4 5). suma := 0. numeros do: [ :unNumero | suma := suma + unNumero]. ^suma

Este ejemplo ejecuta el bloque de código para cada número en la colección con la variable temporal unNumero apuntando al número. El siguiente diagrama ilustra esta iteración:

Página 49

Page 50: Manual de Smalltalk

Manual de Smalltalk - Ing. Lucas Spigariol

Veamos otro ejemplo. El siguiente código cuenta el número de de números pares en una colección. Obtiene el resultado de 2.

"Cuenta el número de números pares en numeros." |numeros pares| numeros := #(1 2 3 4 5). pares := 0. numeros do: [:unNumero | unNumero even ifTrue: [pares := pares + 1]]. ^pares

Los números reconocen un mensaje llamado even que devuelve true si el número es par, y devuelve false si es impar.

add: unObjeto

El mensaje add: agrega un objeto, especificado por el argumento unObjeto, a la colección. El mensaje sólo es válido para las colecciones que pueden crecer en tamaño. Este mensaje devuelve el objeto que fue agregado.

|unaColeccion| unaColeccion := Bag new. unaColeccion add: 1

remove: unObjeto

El mensaje remove elimina un objeto de la colección. El mensaje sólo es válido para las colecciones que pueden crecer o disminuir en tamaño. El mensaje devuelve el objeto eliminado. Si el objeto no es encontrado, será visualizada la ventana de depuración (debugger window).

|unaColeccion| unaColeccion := Bag new. unaColeccion add: 1. unaColeccion remove: 1.

at: unNúmero put: unObjeto

El mensaje at: put: coloca un objeto, especificado por el argumento unObjeto, en la colección en el índice especificado por el argumento unNúmero. El mensaje devuelve el objeto colocado en la colección. Es mensaje sólo es válido para las colecciones que pueden ser indexadas. El índice debe ser un número válido. |unaColeccion| unaColeccion := Array new: 10. unaColeccion at: 5 put: 'cadena 5'. ^unaColeccion

Página 50

Page 51: Manual de Smalltalk

Manual de Smalltalk - Ing. Lucas Spigariol

at: unNúmero

El mensaje at: devuelve el objeto en el índice especificado por el argumento unNúmero. El mensaje es válido para las colecciones que pueden ser indexadas.

|unaColeccion| unaColeccion := Array new: 10. unaColeccion at: 5 put: 'cadena 5'. unaColeccion at: 5

, unaColección

El mensaje combina dos colecciones para formar una tercera colección por concatenación. El receptor del mensaje debe ser una colección que pueda ser indexada. El argumento unaColección puede ser cualquier tipo de colección. El mensaje devuelve una nueva colección de la misma clase que el receptor.

Este mensaje es una buena forma de hacer crecer a una colección de tamaño fijo. Por ejemplo, al crear un vector y luego agregar un nuevo elemento al vector.

|unaColeccion| unaColeccion := Array new: 2. unaColeccion at: 1 put: 'cadena 1'. unaColeccion at: 2 put: 'cadena 2'. unaColeccion := unaColeccion, (Array with: 'cadena 3').

detect: unBloque

Este mensaje devuelve el primer elemento en el receptor para el cual la evaluación del argumento unBloque es verdadera.

#( 4 7 10 3 7) detect: [ :nro | nro > 7] ifNone: [^nil].

Esta sentencia devolverá el número 10.

select: unBloque

Este mensaje devuelve un subconjunto del receptor conteniendo todos aquellos elementos para los cuales la evaluación del argumento unBloque es verdadera.

'ahora es el momento' select: [:letra | letra isVowel ]

Devuelve la colección formada por: a o a e e o e o.

Página 51

Page 52: Manual de Smalltalk

Manual de Smalltalk - Ing. Lucas Spigariol

reject: unBloque

Este mensaje devuelve un subconjunto del receptor conteniendo aquellos elementos para los cuales la evaluación del argumento unBloque es falsa.

'ahora es el momento' reject: [:letra | letra isVowel ]

Devuelve la colección formada por: h r s l m m n t.

collect: unBloque

Este mensaje crea y devuelve una nueva colección del mismo tamaño que la receptora. Los elementos de la nueva colección son el resultado de ejecutar el argumento unBloque en cada uno de los elementos del receptor.

#('ahora' 'es' 'el' 'momento' 123) collect: [:elemento | elemento isString ]

Devuelve la colección formada por: true true true true false.

Resumen de colecciones y mensajes

La siguiente tabla resume los métodos que cada colección soporta.

COLECCIONES do: add: remove: at: at:put:

, detect:

select: reject: collect:

Bag S S S N N N S S S S

Set S S S N N N S S S S

Array S N N S S S S S S S

OrderedCollection

S S S S S S S S S S

SortedCollection S S S S N S S S S S

Dictionary S S N S S N S S S S

String S N N N S S S S S S

Symbol S N N N S S S S S S

Colecciones Especiales

Hay otras tres colecciones que son útiles pero que difieren bastante de las otras colecciones ya vistas, lo que amerita una discusión especial. Las tres clases son String, Symbol, y Dictionary.

Página 52

Page 53: Manual de Smalltalk

Manual de Smalltalk - Ing. Lucas Spigariol

String

Lógicamente la clase String es idéntica a la clase Array con la excepción que sólo puede contener caracteres. Por ejemplo, vea el siguiente diagrama de la cadena 'John':

Inspeccione, con la herramienta Inspect de Smalltalk, la siguiente cadena:

'Fernando'

La ventana de Inspección se abre y muestra el contenido de la cadena. Note que la cadena está compuesta de ocho elementos, cada uno de ellos apuntando a un caracter.

Una cadena no puede crecer o disminuir en tamaño, pero puede ser indexada. Por lo tanto, soporta los mensajes at: y at:put:, pero no soporta los mensajes add: o remove:. Los mensajes que parecen hacer crecer a un objeto String crean un nuevo objeto String en vez de hacer crecer al objeto existente.

Las cadenas tienen métodos adicionales que sólo tienen sentido para una cadena de caracteres.

' hola' trimBlanks “Devuelve una cadena sin los espacios iniciales."'Marzo 10, 2000' upTo: $, "Devuelve una cadena hasta el primer caracter ingresado."'uno dos ' asArrayOfSubtrings “Devuelve un vector de cadenas por cada palabra en la

cadena principal."

Symbol

Los objetos Symbol son usados por las clases para definir los selectores para los métodos definidos por la clase. Por ejemplo, si la clase Cliente tiene un método llamado nombre, entonces el símbolo para el selector es #nombre. Los símbolos también son usados para obtener claves únicas en los diccionarios. Sin embargo, los átomos también pueden ser utilizados para esto.

Página 53

Page 54: Manual de Smalltalk

Manual de Smalltalk - Ing. Lucas Spigariol

La clase Symbol es similar a la clase String, con algunas diferencias únicas. Posee el siguiente comportamiento:

Un símbolo es un objeto de sólo lectura una vez que ha sido creado.

Un símbolo es único. No pueden existir dos símbolos con el mismo valor.

Un símbolo no vacío sólo puede ser creado utilizando un literal como:

|unaColeccion| unaColeccion := #Simbolo.

Esto significa que no soporta los mensajes: new:, with:, with: with:, with: with: with:, y with: with: with: with:.

Sí soporta el mensaje , (coma) pero devuelve una nueva cadena, y no un nuevo símbolo.

#nombre1, #nombre2

Recuerde que un símbolo es precedido por el signo numeral. Un símbolo es fijo en tamaño. No puede crecer o decrecer. Esto

significa que no soporta mensajes como add:.

Un símbolo es de sólo lectura; una vez creado no puede ser modificado. Esto significa que no soporta ningún método que pueda cambiar su valor como at:put:.

Dictionary

Un objeto dictionary es como una base de datos simple. Los diccionarios son colecciones desorganizadas cuyos elementos son accedidos por una clave externa explícitamente asignada. Las claves usualmente son cadenas o símbolos, pero en principio cualquier objeto puede ser usado como una clave de diccionario. Los diccionarios mantienen un seguimiento de las parejas clave/valor. Cada par clave/valor es una instancia de una clase llamada Association. Una instancia de asociación apunta a un objeto que es una clave y apunta a un objeto que es el valor. Un elemento en un diccionario contiene un puntero a una instancia de asociación. No hay restricciones sobre los elementos que se guardan en un diccionario.

Página 54

Page 55: Manual de Smalltalk

Manual de Smalltalk - Ing. Lucas Spigariol

Las claves deben ser únicas en un diccionario, por lo que no habrá dos asociaciones en un diccionario que tengan claves con el mismo valor.

El apareo de claves para el almacenamiento o acceso de los elementos está basado en la operación de igualdad =. Consecuentemente, las claves deben ser únicas con respecto a la operación de igualdad, que es, dos elementos no pueden estar asociados a la misma clave ni dos claves pueden ser iguales. Por ejemplo, si un objeto String con el valor 'nombre' está actualmente almacenado como clave, otro objeto String con el mismo valor no puede ser agregado como clave.

Debido a los pares clave/valor, varios de los métodos para la clase Dictionary son un poco diferentes de los métodos para las otras colecciones. La clase Dictionary también ofrece varios métodos adicionales específicos para claves y valores.

Los siguientes párrafos brevemente resumen algunos de los más comunes métodos para diccionarios.

Algunos de los ejemplos necesitan que los inspeccione. Cuando se ejecuta el comando Show it sobre un objeto Dictionary sólo se ven sus valores y no sus claves. Una Ventana de Inspección se necesita para ver las claves y los valores.

add: unaAsociacion

El mensaje add: agrega el argumento unaAsociacion al diccionario. Devuelve la asociación que fue agregada. Inspeccione el siguiente ejemplo:

Dictionary new add: (Association key: '45841122'); yourself

removeKey: unaClave

El mensaje removeKey:elimina una asociación del diccionario con la clave igual al argumento unaClave. El mensaje devuelve el valor de la asociación que fue eliminada. Si el argumento unaClave no es

Página 55

Page 56: Manual de Smalltalk

Manual de Smalltalk - Ing. Lucas Spigariol

encontrado en el diccionario se visualizará la ventana de depuración. Inspeccione el siguiente ejemplo:

|unDiccionario| unDiccionario := Dictionary new. unDiccionario add: (Association key: '45841122' value: 'Rodríguez, Manuel'). unDiccionario removeKey: '45841122'

at: unaClave

El mensaje at: devuelve el valor asociado con el argumento unaClave. Si unaClave no existe en el diccionario se visualizará la ventana de depuración.

|unDiccionario| unDiccionario := Dictionary new. unDiccionario add: (Association key:'45841122' value:'Rodríguez, Manuel'). unDiccionario at:'45841122'

keyAtValue: unValor

El mensaje keyAtValue: devuelve la clave del primer valor que encuentra que es igual al argumento unValor. Si el argumento unValor no se encuentra en el diccionario, se visualizará la ventana de depuración.

|unDiccionario| unDiccionario := Dictionary new. unDiccionario add: (Association key:'45841122' value:'Manuel'). unDiccionario keyAtValue:'Manuel'

at:unaClave put:unValor

El mensaje at: put: encuentra el argumento unaClave en el diccionario y reemplaza su valor por el argumento unValor. Si la clave no se encuentra, entonces se agrega al diccionario. Este mensaje puede ser utilizado en lugar del mensaje add: para agregar una nueva asociación al diccionario. Este mensaje devuelve unValor.

|unDiccionario| unDiccionario := Dictionary new. unDiccionario add: (Association key:'45841122' value:'Manuel'). unDiccionario at:'45841122' put:'Felipe'. unDiccionario at:'45820022' put:'Tía Claudia'. unDiccionario

Note que el valor para la clave '45841122' ha sido modificado y una nueva asociación con la clave '45820022' y el valor 'Tía Claudia' ha sido agregado.

do: unBloque

Página 56

Page 57: Manual de Smalltalk

Manual de Smalltalk - Ing. Lucas Spigariol

El mensaje do: realiza iteraciones a través de todos los elementos del diccionario, ejecutando un bloque de código de un sólo argumento especificado por el argumento unBloque, el argumento de dicho bloque se corresponde con los valores de cada asociación.

|unDiccionario unaColeccion| unDiccionario := Dictionary new. unaColeccion := OrderedCollection new. unDiccionario at:'45841122' put:'Manuel'. unDiccionario at:'45820022' put:'Tía Claudia'. unDiccionario do:[:nombre |unaColeccion add:'Nombre = ',nombre]. ^unaColeccion

Este ejemplo devuelve una Colección Organizada donde cada elemento apunta a un objeto String con el nombre de la persona precedido por la cadena 'Nombre = '.

keysDo: unBloque

El mensaje keysDo: realiza iteraciones a través de todos los elementos del diccionario, ejecutando un bloque de código de un sólo argumento especificado por el argumento unBloque, donde cada argumento de dicho bloque se corresponde con la clave de cada asociación.

|unDiccionario unaColeccion| unDiccionario := Dictionary new. unaColeccion := OrderedCollection new. unDiccionario at:'45841122' put:'Manuel'. unDiccionario at:'45820022' put:'Tía Claudia'. unDiccionario keysDo:[:tel |unaColeccion add:'Teléfono = ',tel]. ^unaColeccion

Este ejemplo crea una Colección Ordenada con cada elemento apuntando a un objeto String con el teléfono precedido por la cadena 'Teléfono = '.

keys

El mensaje keys devuelve un conjunto con todas las claves del diccionario.

|unDiccionario| unDiccionario := Dictionary new. unaColeccion := OrderedCollection new. unDiccionario at:'45841122' put:'Manuel'. unDiccionario at:'45820022' put:'Tía Claudia'. unDiccionario keys

values

Página 57

Page 58: Manual de Smalltalk

Manual de Smalltalk - Ing. Lucas Spigariol

El mensaje values devuelve una instancia de la clase Bag con todos los valores del diccionario.

|unDiccionario| unDiccionario := Dictionary new. unaColeccion := OrderedCollection new. unDiccionario at:'45841122' put:'Manuel'. unDiccionario at:'45820022' put:'Tía Claudia'. unDiccionario values

¿Por qué el diccionario devuelve las claves en un Conjunto y los valores en una Bolsa? Un Conjunto no permite duplicados, mientras que una Bolsa sí lo hace. Un objeto Dictionary no puede tener claves duplicadas, entonces un Conjunto es una buena elección. Pero como un objeto Dictionary puede tener valores duplicados, se colocan en una Bolsa.

Página 58

Page 59: Manual de Smalltalk

Manual de Smalltalk - Ing. Lucas Spigariol

Glosario:

Abstracción: Una descripción o vista simplificada de algo que enfatiza las características o los propósitos relevantes al usuario, mientras que suprime los detalles que son inmateriales o de distracción.

Argumento: Es un dato incluido como parte de un mensaje. Los argumentos proporcionan información adicional que el receptor puede utilizar para realizar la operación solicitada. Los mensajes binarios y los mensajes de palabra clave toman argumentos. En un mensaje de palabra clave, los dos puntos ( : ) después de una palabra clave indican que se necesita un argumento.

Clase: Una clase es un objeto que especifica las propiedades generales para los tipos específicos de objetos. Esto incluye la descripción de los atributos, de los comportamientos, y de la implementación de un objeto. Los objetos representados por una clase se llaman instancias de la clase. Estas clases se disponen jerárquicamente desde superclases menos específicas hacia subclases más específicas. Las subclases heredan las propiedades de sus superclases. Todas las acciones a las cuales un objeto responde se definen en la descripción de su clase.

Clase abstracta: Es una clase que proporciona un comportamiento común a sus subclases, pero no se diseña para generar instancias a partir de ella.

Comportamiento: (1) Es el conjunto externo de características que exhibe un objeto. (2) Es la clase abstracta que proporciona un comportamiento común para las clases y metaclases.

Colección: Es un conjunto de elementos, donde cada elemento es un objeto.

Comentario: Es un conjunto de caracteres encerrados entre comillas dobles. Smalltalk ignora los comentarios y no los ejecuta.

Definición de la clase: La definición de una clase contiene:

El nombre de la clase El tipo de clase La superclase inmediata para la clase Las variables de instancia y de clase Los diccionarios compartidos que la clase usa

Página 59

Page 60: Manual de Smalltalk

Manual de Smalltalk - Ing. Lucas Spigariol

Diccionario: En Smalltalk, es una colección desordenada cuyos elementos son accedidos por una clave externa explícitamente asignada. Véase también pool dictionary (Diccionarios Compartidos).

Diccionario Compartido (Pool Dictionary): Es un objeto del tipo diccionario cuyas claves definen variables que pueden ser compartidas por múltiples clases. Todos los métodos para una clase pueden acceder a las variables que se encuentran en un Diccionario compartido como parte de su alcance.

Encapsulamiento: Oculta la representación de los datos internos de un objeto. El objeto proporciona una interfaz que consulta y manipula los datos sin exponer su estructura interna. El objeto solamente dice qué puede hacer pero no cómo lo hace.

Herencia: Es la relación entre las clases en las cuales una clase comparte su estructura y comportamiento de otra. Una subclase hereda todo de una superclase.

Instancia: Es un objeto que es una ocurrencia particular de una determinada clase. Una instancia existe en memoria o en un medio externo en forma permanente.

Jerarquía de clases: Es una estructura de árbol que define las relaciones entre las clases. Una clase tiene subclases bajo ellas, y superclases por encima de ella, jerárquicamente hablando. Los métodos y las variables de una clase son heredados por sus subclases.

Literal: Es un objeto creado por el compilador. Un literal puede ser un número, una cadena de caracteres, un caracter, un símbolo, ó un vector. Todos los literales son únicos: dos literales con el mismo valor referencian al mismo objeto. El objeto creado por un literal es inalterable: no puede ser modificado.

Mensaje: Es la comunicación de un objeto a otro que solicita que el objeto receptor ejecute un método. Un mensaje consiste en una referencia al objeto receptor, seguido por un selector indicando el método solicitado, y (generalmente) los argumentos que son usados por el método. Hay tres tipos de mensajes: binarios, de palabra clave, y unarios. También puede hacerse una clasificación de acuerdo al receptor, esta puede ser mensajes de instancia ó mensajes de clase, según el receptor sea una instancia ó una clase.

Mensaje Binario: Un mensaje que especifica una acción que se realizará en el objeto receptor y un objeto adicional pasado como argumento. En Smalltalk se utiliza los mensajes binarios para la aritmética, las comparaciones y las operaciones lógicas. El nombre de

Página 60

Page 61: Manual de Smalltalk

Manual de Smalltalk - Ing. Lucas Spigariol

estos mensajes no debe tener ningún carácter alfanumérico. X + Y es un ejemplo de un mensaje binario con + como el selector binario.

Mensaje de palabra clave: Es un mensaje que recibe uno ó más argumentos. Una palabra clave es un identificador seguido por dos puntos ( : ). Cada palabra clave requiere un argumento, y el orden de las palabras claves es importante. 'hola' at:2 put: $H es un ejemplo de un mensaje de palabra clave ; at: y put: son los selectores de la palabra clave, 2 y $H son los argumentos. Esto es lo que lo diferencia de los mensajes binarios y de los mensajes unarios. Véase también Mensaje.

Mensaje unario: Es un mensaje que no posee argumentos, size es un ejemplo de un mensaje unario.

Metaclase: Es la especificación de una clase; es la completa descripción de los atributos, comportamiento e implementación de una clase. Toda clase tiene una metaclase de la cual es su instancia. Compare con clase

Método: Es el código ejecutable que implementa la lógica de un mensaje particular de una clase. Hay dos tipos de métodos: método de clase y método de instancia.

Método de Clase: Es un método que proporciona el comportamiento para una clase. El mensaje para invocar métodos de clase se envía a la clase, y no a la instancia de la clase.

Método de Instancia: Un método que proporciona el comportamiento para las instancias de la clase. Los mensajes que invocan métodos de instancia se envían a las instancias particulares y no a la clase.

nil: Es el objeto que en Smalltalk significa "sin valor". Todas las variables en un principio son inicializadas a nil. Es la única instancia de la clase UndefinedObject.

objeto: Es el bloque de construcción básico en el desarrollo de Smalltalk. Un objeto es cualquier cosa que puede mostrar un comportamiento, o sea, a la que se le puede asignar responsabilidades. Todo el código y los datos de Smalltalk deben ser parte de un objeto.

Polimorfismo: Es la capacidad de los objetos que, siendo diferentes, pueden responder a un mismo mensaje de maneras diferentes. Esto significa que objetos diferentes pueden tener implementaciones de métodos diferentes para un mismo mensaje. Un objeto puede enviar un mensaje sin importarle como el receptor implementa el mensaje.

Página 61

Page 62: Manual de Smalltalk

Manual de Smalltalk - Ing. Lucas Spigariol

Programación Orientada a Objetos: Es una metodología de programación construida alrededor de objetos y se basa en la interacción de los objetos mediante el envío de mensajes. Los conceptos básicos de la programación orientada a objetos son la encapsulamiento, herencia y polimorfismo.

Redefinición: Es cuando se vuelve a definir un método que ya existe en alguna clase superior (superclase).

Self: Es una pseudovariable que hace referencia al receptor de un mensaje. Se utiliza dentro de un método de una clase para poder enviar un mensaje al objeto receptor del mensaje original. La búsqueda de ese nuevo mensaje comienza a partir de la clase a la que pertenece el receptor.

Subclase: Es una clase que hereda el comportamiento y las especificaciones, es decir, los métodos y las variables, de otra clase.

Super: Es una pseudovariable que hace referencia al receptor de un mensaje. Se utiliza dentro de un método de una clase para poder enviar un mensaje al objeto receptor del mensaje original. La diferencia con self es que con super la búsqueda comienza a partir de la superclase del objeto receptor. Con super podemos hacer referencia a métodos redefinidos en esa clase.

Superclase: Es una clase de la cual otra clase hereda el comportamiento y las especificaciones, o sea, los métodos y variables.

Variable: Un lugar de almacenamiento dentro de un objeto para un dato, donde el dato es un objeto.

Variable de clase: Son los datos compartidos por la clase que la define y sus subclases. Los métodos de instancia y los métodos de clase, de la clase y sus subclases, pueden referirse directamente a estos datos. Al cambiar el valor de una variable de clase en una clase, también cambia para todas las otras clases que hereden esta variable.

Variable de instancia: Son los datos privados que pertenecen a una instancia de una clase, y están ocultos a los accesos directos por parte del resto de los objetos. Las variables de instancia pueden ser accedidas solamente por los métodos de instancia de la clase y sus subclases. El conjunto de variables de instancias define las características particulares de un objeto; o sea, si bien todos los objetos de esa clase tienen la misma cantidad de variables de instancia, sus valores son diferentes.

Variable de instancia de la clase: Es la información privada que le pertenece a una clase. La clase que la define y cada una de sus

Página 62

Page 63: Manual de Smalltalk

Manual de Smalltalk - Ing. Lucas Spigariol

subclases mantienen su propia copia de la información. Cambiar la información en una clase no la cambia en todas las clases de la jerarquía, a diferencia de lo que ocurre con las variables de clase

Variable Temporal: Es una variable cuyo alcance está limitado al método ó bloque donde está definida. Una variable temporal toma un valor asignado.

Página 63