You are on page 1of 63

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


Manual de Smalltalk - Ing. Lucas Spigariol

Contenido
Capí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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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

Página 19
Manual de Smalltalk - Ing. Lucas Spigariol

Cuando Smalltalk procesa cada mensaje, la instrucción en el mensaje


se reemplaza por un valor retornado, que es el resultado de ejecutar
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.

Página 20
Manual de Smalltalk - Ing. Lucas Spigariol

Devolución de Valores
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.

Página 21
Manual de Smalltalk - Ing. Lucas Spigariol

Por ejemplo:

^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

Página 22
Manual de Smalltalk - Ing. Lucas Spigariol

Las variables temporales están definidas en la definición de interfase


de un método.

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.

Página 23
Manual de Smalltalk - Ing. Lucas Spigariol

• 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
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]

Página 24
Manual de Smalltalk - Ing. Lucas Spigariol

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:

[: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.

Página 25
Manual de Smalltalk - Ing. Lucas Spigariol

Si las tres instrucciones se combinan en una sola con self adelante de


cada palabra clave, de la siguiente manera:

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
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
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
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"

|xy|
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
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"

|ij|
i := 3.

Página 30
Manual de Smalltalk - Ing. Lucas Spigariol

j := 7.
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:

|xyz|
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.

Página 31
Manual de Smalltalk - Ing. Lucas Spigariol

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.

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:

|xyz|
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].

Página 32
Manual de Smalltalk - Ing. Lucas Spigariol

^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.

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]

Página 33
Manual de Smalltalk - Ing. Lucas Spigariol

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.

"Itera mientras x es menor que y"


|xy|
x := 5.
y := 0.
[x < y] whileFalse: [y := y + 1].
^y

"Itera hasta que y es mayor than x"


|xy|
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
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
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
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
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
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
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
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
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
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
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:

Tamaño Duplicado
COLECCIONES Indexación Orden Contenidos
variable s
Cualquier objeto, pero
Bag N S S N
no nil
Cualquier objeto, pero
Set N S N N
no nil
Array S N S N Cualquier Objeto
OrderedCollectio
S S S N Cualquier objeto
n
SortedCollection S S S S Cualquier objeto
String S N S N Caracteres
Symbol S N N N Caracteres
Clave + Cualquier
Dictionary N S N N
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

Página 44
Manual de Smalltalk - Ing. Lucas Spigariol

• proveen un estructura de datos básica para la programación


• 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

Página 45
Manual de Smalltalk - Ing. Lucas Spigariol

Array (Vector o Arreglo)

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
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:

Página 47
Manual de Smalltalk - Ing. Lucas Spigariol

new

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.

Página 48
Manual de Smalltalk - Ing. Lucas Spigariol

size

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
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

Página 50
Manual de Smalltalk - Ing. Lucas Spigariol

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

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.

Página 51
Manual de Smalltalk - Ing. Lucas Spigariol

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.

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.

at: detect
COLECCIONES do: add: remove: at: , select: reject: collect:
put: :
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
OrderedCollectio
S S S S S S S S S S
n
SortedCollection S S S S N S S S S S

Página 52
Manual de Smalltalk - Ing. Lucas Spigariol

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.

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

Página 53
Manual de Smalltalk - Ing. Lucas Spigariol

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.

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

Página 54
Manual de Smalltalk - Ing. Lucas Spigariol

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.

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

Página 55
Manual de Smalltalk - Ing. Lucas Spigariol

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
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

Página 56
Manual de Smalltalk - Ing. Lucas Spigariol

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

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.

Página 57
Manual de Smalltalk - Ing. Lucas Spigariol

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

values

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
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
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
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
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
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

You might also like