Squeak Smalltalk apu(...)

Anuncio
Tabla de Contenidos
INTRODUCCIÓN AL LENGUAJE SMALLTALK.......................................... 2
1. BREVE RESEÑA HISTÓRICA .................................................................. 2
2. ELEMENTOS DE SMALLTALK ............................................................... 2
2.1. OBJETOS Y VARIABLES. ........................................................................... 2
2.2. MENSAJES ............................................................................................. 4
2.2.1. EXPRESIONES .............................................................................................................. 5
2.2.2. EXPRESIONES EN CASCADA ......................................................................................... 5
2.2.3. MENSAJES DENTRO DE MENSAJES ............................................................................... 5
2.3. SOBRE EL USO DE SQUEAK SMALLTALK................................................ 5
2.4. MÉTODOS .............................................................................................. 6
2.3.1. MENSAJE NEW A UNA CLASE ........................................................................................ 7
2.5. CONTROL ............................................................................................... 7
2.4.1. SELECCIÓN E ITERACIÓN .............................................................................................8
2.6. CLASES.................................................................................................. 9
2.6.1. CÓMO SE DEFINE UNA NUEVA CLASE EN SQUEAK SMALLTALK ................................ 10
Sobre la Redefinición del Método new y la Pseudo Variable super.............................. 13
2.7. HERENCIA ............................................................................................13
Introducción al Lenguaje Smalltalk
1. Breve reseña histórica
Desde sus orígenes Smalltalk fue concebido para ser mucho más que un lenguaje
de programación; la idea fue diseñar un ambiente de programación que integrara
software y hardware, y transformara a la computadora en una herramienta fácil de
usar. El sistema Smalltalk puede ser pensado como compuesto por cuatro elementos
básicos:
El kernel del lenguaje de programación.
El paradigma de programación.
El sistema de programación
El modelo de interface con el usuario.
Estos componentes son básicamente jerárquicos: la interface del usuario se
implementa sobre el sistema de programación, el cual a su vez está construido
siguiendo el paradigma de programación y usando el kernel. El kernel del lenguaje
de programación es el compilador o intérprete del lenguaje, que determina la
semántica y la sintaxis. El paradigma de programación es el estilo de uso del
kernel, es decir, una vista del significado asignado a las entidades del mismo. El
sistema de programación es el conjunto de objetos y clases del sistema necesarias
para llevar a cabo la programación; este sistema brinda la estructura fundamental y
resume en una colección jerárquica de clases la concepción de la programación en
Smalltalk. Por último, la interface gráfica del usuario representa la utilización de
las herramientas incorporadas para presentar el sistema al usuario. La combinación de
todas estas piezas conforma el denominado sistema Smalltalk.
El proyecto original consistió en integrar en una única plataforma de software y
hardware el ambiente de programación arriba descripto. El componente de hardware
tal vez no tuvo el éxito esperado por razones ajenas al proyecto mismo, la década
pasada estuvo particularmente afectada por la aparición de la computadora personal
cuyo impacto muchas veces no fue dimensionado con la anticipación necesaria. Pero el
componente de software, es decir el sistema denominado Smalltalk/80, se convirtió
en uno de los pasos fundamentales en el camino de la evolución de la programación
orientada a objetos, el paradigma que más ha crecido en los últimos años. Smalltalk
no sólo logró un interesante éxito en las aplicaciones industriales y administrativas sino
que se convirtió en el soporte de los cursos universitarios de orientación a objetos.
2. Elementos de Smalltalk
2.1. OBJETOS Y VARIABLES.
En Smalltalk, cada cosa es un objeto. No hay manera de crear dentro del lenguaje
una entidad que no sea un objeto. Desde el punto de vista de la implementación, los
objetos son sólo un conjunto de celdas de memoria que se asignan dinámicamente.
Estas celdas mantienen el estado del objeto y a diferencia de otros lenguajes las
variables no almacenan el valor que representan, sino un puntero al objeto (ver figura
1). Esta propiedad es muchas veces referida como semántica de puntero.
Figura 1. Implementación de un Objeto en Smalltalk
En Smalltalk existen distintas categorías de identificadores, por ejemplo,
nombres y variables de clase, variables de instancia, variables globales, pseudo
variables, mensajes, etc. Es importante notar que el lenguaje es sensible a mayúsculas y
minúsculas. Los nombres y variables de clase deben comenzar con letras mayúsculas,
mientras que las variables de instancia, pseudo variables con minúsculas.
Los atributos de un objeto pueden ser de dos tipos, variables de clase y variables de
instancia. Las variables de clase guardan atributos comunes a todas las instancias
de una misma clase. Por lo tanto, estos atributos son accesibles a la clase y sus
subclases, así como también a todos los objetos que son instancia de dichas clases. Por
ejemplo, si tenemos una clase Párrafo una variable de clase puede ser sangría. Así,
todos los párrafos tendrán siempre la misma sangría. En términos semánticos, si un
párrafo modifica dicho atributo, estará modificando la sangría de todos los párrafos.
En cambio, las variables de instancia tienen valores asociados únicamente con
cada instancia u objeto creado a partir de una clase. La única manera de acceder y
modificar dichos valores es a través de los métodos pertenecientes al protocolo del
objeto. Por ejemplo, dada la clase Persona, una variable de instancia es el nombre de la
persona. Es claro, que cada instancia de la clase Persona tendrá un nombre distinto.
También es posible definir variables globales o compartidas. Estas variables son
definidas en diccionarios llamados “pools”. Diferentes tipos de variables globales son
definidas en diferentes tipos de pools. Todas las variables globales, al igual que las
variables de clase, comienzan con letras mayúsculas. El nombre de la variable y su valor
son ligados dentro de un objeto el cual es una instancia de la clase Association. Esta
instancia es ubicada dentro de un pool. En particular, el “System Dictionary Smalltalk”
es un pool que contiene todas las variables globales, las cuales son accesibles a todos los
objetos. Note que las variables de clase son un caso particular de variables compartidas,
las cuales son implícitamente almacenadas dentro de un pool definido para la clase.
Retornando a la implementación, las variables en Smalltalk recuerdan a los
campos de un registro en lenguajes como Pascal pero con algunas diferencias. Por
ejemplo, en las variables de instancia el ámbito de referencia está delimitado por el
objeto donde se encuentra la definición. Otra diferencia es que las variables son
sencillamente designadores de objetos, es decir son uniformes con respecto al espacio
ocupado por la referencia más allá del objeto referenciado y en este sentido no tienen
un tipo asociado. Además de las variables de instancia y de clase cada objeto tiene
asignada una pseudo variable denominada self. Self es un designador de objeto que
representa al objeto receptor del mensaje, luego veremos que la combinación de esta
variable con la herencia conforma una herramienta muy poderosa.
Finalmente, Smalltalk tiene variables temporales. Las variables temporales
están asociadas a un fragmento de código. Las mismas se crean cada vez que se ejecuta
dicho código. El espacio ocupado por estas variables es desalocado cada vez que finaliza
la ejecución del fragmento. Sintácticamente, las variables temporales son declaradas
entre barras, al principio del código al que están vinculadas, y sus identificadores deben
comenzar con letra minúscula. Esta categoría de variables es utilizada por los métodos.
2.2. MENSAJES
La computación en Smalltalk tiene lugar como resultado de enviar mensajes a los
objetos. La sintaxis indica que un mensaje se compone de una referencia al objeto
receptor seguido por un indicador del mensaje en cuestión, denominado selector del
mensaje, seguido de cero o más argumentos. La semántica asociada a los mensajes
puede recordar las llamadas a los procedimientos, pero establece otro orden entre los
componentes del lenguaje. En la programación imperativa el control ocupa el centro
del diseño mientas que en la POO los mensajes y métodos están subordinados al
concepto de objeto.
En Smalltalk existen tres tipos de mensajes: unarios, binarios y de palabra clave.
Los mensajes unarios no tienen argumentos y deben comenzar con una letra
minúscula, por ejemplo:
pilaUno desapilar
pilaUno es el objeto receptor del mensaje, mientras que desapilar es el método o acción
que se le solicita a dicho objeto. Naturalmente, el método desapilar debe formar parte
del protocolo del objeto pilaUno.
En cambio, los mensajes binarios, permiten pasar un argumento y su selector está
formado por uno o dos caracteres no alfabéticos adyacentes. En general, se emplean
para operaciones aritméticas y relacionales. Por ejemplo:
x<y
En este caso x es el objeto receptor del mensaje, el objeto y es el argumento y < es el
selector. Como respuesta a este mensaje, x devolverá el objeto true ó el objeto false.
Por otra parte, los mensajes de palabra clave permiten pasar uno o más
argumentos:
pilaUno apilar: 80
En este caso estamos pidiendo al objeto pilaUno que apile el objeto 80.
Otro ejemplo es:
vectorA at: 3 put: 19
En este caso vectorA es una instancia de la clase Array, y el mensaje at:put: esta
indicando al objeto vectorA que asigne el objeto 19 al objeto que se encuentra en la
posición 3 de su arreglo. Note que cada argumento tiene asociado una palabra clave, la
cual debe comenzar con una letra minúscula.
Finalmente, un objeto se puede enviar un mensaje a sí mismo mediante el uso de la
pseudo variable self. Para ilustrar esto, asumamos que el objeto pilaUno contiene el
siguiente método:
apilar: unElem
(self estaLlena)
ifTrue: [self error: ‘pila llena’]
ifFalse: [tope := tope + 1.
elementos at: tope put: unElem]
En este caso, self estaLlena es un mensaje que pilaUno se envía a sí misma para saber si
se encuentra vacía (esto es, la búsqueda del selector error: comenzará en la clase de la
cual pilaUno es intancia).
2.2.1. Expresiones
Un párrafo aparte merece el tratamiento de expresiones por parte de Smalltalk.
Como hemos observado antes, los números son objetos. En particular, 3 es una
instancia de la clase Integer, 7.43 es una instancia de la clase Float y 4/7 es una
instancia de la clase Fraction. De este modo la siguiente expresión:
x := 3 + 4
asigna al objeto x el resultado de enviar el mensaje + al objeto 3 pasando como
argumento el objeto 4. En definitiva, x quedará asociado el objeto 7.
Es importante destacar que en Smalltalk la evaluación de las expresiones se
realiza de izquierda a derecha. Además, todos los operadores tienen la misma
precedencia, de este modo en la siguiente expresión 2 + 3*5 primero se efectúa la suma,
luego el resultado es el objeto 25.
2.2.2. Expresiones en Cascada
Existen situaciones en que necesitamos enviar varios mensajes al mismo objeto en
forma consecutiva. Por ejemplo, suponga que se desea crear una pila e inmediatamente
apilarle los elementos 1 y 2. Luego, se debería enviar la siguiente secuencia de
mensajes: pilaUno := Pila new. pilaUno apilar: 1. pilaUno apilar: 2
Donde el mensaje new crea una instancia de la clase Pila y el mensaje apilar apila un
elemento en un objeto de la clase Pila. Para estos casos, Smalltalk provee un tipo
especial de expresiones conocidas como expresiones en cascada, las cuales
permiten enviar múltiples mensajes a un mismo objeto. Para nuestro ejemplo, sería
equivalente enviar el mensaje: pilaUno := Pila new; apilar: 1; apilar: 2
2.2.3. Mensajes dentro de mensajes
Los mensajes pueden combinarse en forma poderosa. Al ser combinados, los
mensajes unarios se evalúan en primer término, luego los binarios y finalmente los de
palabra clave. Por ejemplo, en el siguiente mensaje:
‘casa’ size + #( 1 2 3 4) size
Se evalúa primero los mensajes size, dado que son unarios y luego el mensaje +. El
resultado de este mensaje es el objeto 8.
2.3. SOBRE EL USO DE SQUEAK SMALLTALK
Figura 2. Ventana principal de Squeak Samlltalk
Descomprima el archivo “squeak.zip” y ya puede ejecutar el archivo “squeak.exe”.
Este lenguaje no necesita instalación. Una vez ejecutado el archivo squeak.exe se le
presentará la ventana mostrada en la figura 2. Cierre todas las ventanas que están a la
vista (en total debe cerrar 4 ventanas). De esta forma en la pantalla se verán solamente
el gato y las pestañas de los bordes de la ventana principal. Para comenzar a utilizar
Squeak Smalltalk haga clic con el botón izquierdo en cualquier lugar vacío de la
pantalla. De esta forma accede al menú “World” que se muestra en la Figura 2.
Figura 3. Menú World
Las opciones a las que accederemos desde este menú son:
1) Open
2) Save
Una vez elegida la opción “open” podremos optar por abrir workspace o browser,
que serán las dos ventanas con las que trabajaremos. El workspace es el lugar desde el
cual podremos ejecutar expresiones. El browser nos permite modificar y crear nuevas
clases y métodos.
Para evaluar expresiones desde el espacio de trabajo debemos escribir la expresión
a evaluar, seleccionarla y clickear sobre ella con el botón derecho. Para realizar la
evaluación hay tres opciones: Do It, Inspect It o Print It. Investigue la diferencia entre
evaluar una expresión con cada una de estas opciones.
2.4. MÉTODOS
Los objetos responden a los mensajes mediante la ejecución de métodos. Un
método se compone de dos partes: un encabezado y un cuerpo. Como en los lenguajes
tradicionales, el encabezado se utiliza para identificar al método cuando sea invocado y
el cuerpo implementa la operación correspondiente. Por ejemplo, considere el método
apilar correspondiente a la clase Pila:
apilar: unElem
(self estaLlena)
ifTrue: [self error: ‘pila llena’]
ifFalse: [tope := tope + 1. elementos at: tope put: unElem]
El encabezado es apilar: unElem, donde unElem es el argumento del método. El resto
constituye el cuerpo de la operación.
Los métodos existen dentro de los límites demarcados por un objeto y así pueden
acceder a todas las variables de instancias del mismo. Esto resume entonces dos
propiedades simétricas:
•
•
El método de un objeto sólo se interesa por el estado interno de dicho objeto.
Un método no puede afectar directamente las variables de instancia de otro
objeto.
La principal diferencia entre los procedimientos de los lenguajes tradicionales y los
métodos de Smalltalk es el momento en que se ligan la invocación (envío del mensaje)
con la implementación de la operación (método). En Pascal, por ejemplo, esta ligadura
se lleva a cabo en tiempo de compilación, en cambio en Smalltalk se lleva a cabo en
tiempo de ejecución.
2.4.1. Mensaje new a una clase
Los métodos ejemplificados anteriormente son métodos propios de las instancias
de una clase. Sin embargo, de alguna manera debemos crear los objetos. Esto se logra
mediante el envío de un mensaje de creación (new) a la clase del objeto. Por ejemplo, si
deseamos crear el objeto pilaUno como una instancia de la clase Pila se debe realizar la
siguiente asignación:
pilaUno := Pila new
Más adelante, en la sección 2.5 se retomará este tema.
2.5. CONTROL
Las estructuras de control están implementadas mediante el mecanismo de pasaje
de mensajes más una clase predefinida denominada BlockContext. Esta última brinda a
Smalltalk la capacidad de encapsular una secuencia de acciones dentro de un objeto:
el bloque.
Un bloque es una secuencia de expresiones, separadas por puntos, y delimitada por
corchetes. Asimismo, un bloque puede tener argumentos, los cuales son especificados
entre el corchete izquierdo y una barra. Además cada argumento debe ir precedido por
un “:”. Por ejemplo:
[ :j :k | (j*k) printString ]
En el bloque anterior, j y k son parámetros. Dado que un bloque es un objeto, este
puede ser asignado a un identificador ó pasado como argumento de un mensaje. Para
poder ejecutar un bloque sin parámetros, la clase Block provee el método value. Luego,
en posible mandar el mensaje:
[ I := 3. J := 8 printString ] value retornará ‘8’
Siempre, la ejecución de un bloque retorna el resultado de la última expresión evaluada
dentro del mismo. Es importante notar que en respuesta al mensaje value, el bloque se
ejecuta dentro del contexto en que fue definido, independientemente del contexto en
que se encuentra al momento de ser ejecutado. Por ejemplo, suponga que en la clase A
se define el siguiente método:
metA
i := 10.
p := B new.
^ p metB: [i := i+1].
Además, asuma que en la clase B se define el siguiente método metB como sigue:
metB: bloque
i := 3+4.
^ bloque value.
Luego, si a es una instancia de la clase A, y efectuamos la siguiente asignación:
z := a metA
resulta que z queda asignado al objeto 11. Cuando, se evaluó el mensaje ^bloque value,
el objeto i del bloque hace referencia al i asignado en metA y no al empleado en metB.
Por otra parte, para bloques con un argumento se emplea el mensaje value:, para el
caso de dos argumentos el mensaje value:value: y así siguiendo. Por ejemplo:
[ :j :k | (j*k) printString ] value: 2 value: 3 retornará ‘6’
En este caso, j y k quedan asociados a los objetos 2 y 3 respectivamente.
2.5.1. Selección
En Smalltalk las estructuras de control condicionales son implementadas a través de
métodos correspondientes a las subclases True y False de la clase Boolean, los cuales
tienen la siguiente sintaxis:
(<expresión de prueba>) ifTrue: [<secuencia-expresiones>]
y
(<expresión de prueba>) ifFalse: [< secuencia-expresiones>]
La secuencia de expresiones colocada entre corchetes es un bloque sin argumentos.
También es posible utilizarlos de manera combinada. Por ejemplo, para el método
apilar tenemos:
apilar: unElem
(self estaLlena)
ifTrue: [self error: ‘pila llena’]
ifFalse: [tope := tope + 1. elementos at: tope put: unElem]
El mensaje self estaLlena devuelve uno de los objetos: true o false. Si devuelve el objeto
true, entonces se evalúan las expresiones del bloque que sigue a ifTrue:; si devuelve
false, se evalúan las expresiones del bloque que sigue a ifFalse:.
Observe que ifTrue:ifFalse: es un método definido tanto en la clase True como en la
clase False; si el objeto receptor es true entonces se utiliza el método definido en la
clase True, donde se envía el mensaje value al objeto block pasado como argumento en
la palabra clave ifTrue:. Si en cambio, el objeto receptor del mensaje ifTrue:ifFalse: es
false, luego se ejecutará el método ifTrue:ifFalse: de la clase False, donde directamente
se evalúa el bloque correspondiente a la palabra clave ifFalse:.
2.5.2. Repetición
Smalltalk, también define métodos en la clase Block para expresar repetición. Un
bucle while por ejemplo tiene dos formas, la primera:
[<secuencia-expresiones>] whileTrue: [<secuencia-expresiones>]
y la segunda:
[<secuencia-expresiones>] whileFalse: [<secuencia-expresiones>]
En el caso de whileTrue:, el bloque receptor es repetidamente evaluado. Mientras la
evaluación arroje el objeto true, el argumento del bloque es también evaluado, si no
retornará el objeto nil. En el caso de whileFalse: es similar. En todos los casos, los
bloques receptores deben finalizar con una expresión cuyo resultado sea instancia de la
clase Boolean.
Por otra parte, también se proveen métodos de la clase Integer para expresar
repetición. Por caso:
x timesRepeat: [< secuencia de expresiones >]
x to: y do: [< secuencia de expresiones >]
x to: y by: step do: [< secuencia de expresiones >]
Además, la clase Collection provee los denominados ITERADORES. Estos métodos
recorren de manera automática distintas estructuras de datos modeladas mediante
subclases de la clase Collection, tales como la clase Array y String.
Ejemplos:
"cuenta las vocales de un objeto instancia de la clase String usando do:"
| vowels |
vowels := 0.
'Now is the time' do: [ :char | char isVowel ifTrue: [ vowels := vowels + 1 ] ].
^vowels
"dibuja varios polígonos usando do: definido en la clase Array"
Window turtleWindow: 'Turtle Graphics'.
#( 3 4 12 24 ) do: [ :sides | sides timesRepeat: [ Turtle go: 20; turn: 360 // sides ] ]
"cuenta las vocales de un objeto instancia de la clase String usando select:"
('Now is the time' select: [ :c | c isVowel ]) size
El mensaje select: itera sobre el receptor y devuelve en un nuevo String todos los
elementos para los que el bloque se evalúa a true. Luego con size se obtiene la cantidad
de elementos de ese String.
"retorna un arreglo con los dígitos cuyo factorial es < que el dígito elevado a la 4ta
potencia"
#( 1 2 3 4 5 6 7 8 9 ) reject: [ :i | i factorial >= ( i * i * i * i ) ]
"retorna un arreglo con los cuadrados de cada elemento del arreglo receptor"
#(1 13 7 10) collect: [ :i | i * i ]
Implementación de algunos de los métodos presentados anteriormente:
Clase: BlockContext
whileTrue: aBlock
" Evaluate the argument, aBlock, as long as the value of the receiver is true."
self value ifTrue: [ aBlock value. ^self whileTrue: aBlock ]
Clase: Number
timesRepeat: aBlock
"Evaluate the argument, aBlock, the number of times represented by the receiver."
| count |
count := 1.
[count <= self]
whileTrue:
[aBlock value.
count _ count + 1]
to: stop do: aBlock
" Evaluate aBlock for each element of the interval (self to: stop by: 1)."
| nextValue |
nextValue := self.
[nextValue <= stop]
whileTrue:
[aBlock value: nextValue.
nextValue _ nextValue + 1]
Clase: Collection
do: aBlock
1 to: self size do:
[:index | aBlock value: (self at: index)]
La característica más importante de estas estructuras de control es la combinación
de una sintaxis muy sencilla con un mecanismo básico de pasaje de mensajes que
conforman una herramienta de programación muy poderosa y elegante que recuerda a
la programación declarativa. En realidad, los rasgos de la programación imperativa se
ocultan en las profundidades de la jerarquía de clases predefinidas por el sistema.
2.6. CLASES
Una clase brinda la estructura general para objetos con características similares. El
punto más interesante es que en este lenguaje las clases son objetos a los cuales se les
pueden enviar mensajes como a cualquier otro objeto. Todo en Smalltalk es un objeto.
Esta uniformidad extrema se traduce en que, por ejemplo, el debugger incorporado al
ambiente de Smalltalk-80 también está escrito en Smalltalk y puede ser extendido o
adaptado por el programador.
Squeak Smalltalk tiene una gran variedad de clases predefinidas. A estas clases
el programador puede agregar otras, las cuales deberán insertarse dentro de la
estructura jerárquica definida por el lenguaje.
2.6.1. Cómo se define una nueva clase en Squeak Smalltalk
Las descripciones de clases pueden ser ingresadas a través del Browser provisto
por el lenguaje. Para ello, se debe seleccionar la opción Browser dentro del menú
World. A continuación se visualizará la ventana que se muestra en la figura 4.
Figura 4. Browser de clases
En el resto de esta sección crearemos la clase pila. En primer lugar vamos a definir
una nueva categoría en la que incorporaremos todas las clases que definimos. Para esto,
debemos clickear en un cuadrado que se encuentra en la esquina superior derecha de la
sección de categorías de clases (marcado con un rectángulo amarillo en la figura 4). Allí
aparecerá un nuevo menú del que tenemos que seleccionar la opción “add item”.
Escriba en la ventana el nombre que le dará a la nueva categoría (su nombre). Recuerde
que no estamos creando todavía una clase. Solo estamos definiendo la categoría en la
que quedará definida por una cuestión de organización.
Al clickear en el nombre de la nueva categoría verá que la misma está vacía. Ahora
sí procederemos a crear una nueva clase. Para esto debemos decidir quién será la clase
padre. Crearemos la clase Pila como subclase de la clase Object.
Al seleccionar la categoría recién creada podemos ver en la sección de cuerpo de los
métodos una porción de código con la siguiente forma:
Object subclass: #NameOfSubclass
instanceVariableNames: ''
classVariableNames: ''
poolDictionaries: ''
category: 'NuevaCategoría'
Para crear la clase debemos reemplazar NameOfSublclass por Pila. En ese punto se
definen las variables de instancia de la nueva clase. Para nuestro ejemplo son:
elemento, tope y cantMax. El texto queda de la siguiente manera:
Object subclass: #Pila
instanceVariableNames: 'elementos tope cantMax'
classVariableNames: ''
poolDictionaries: ''
category: 'NuevaCategoría'
Posteriormente se guarda esta definición seleccionando la opción Accept del menú
contextual que aparece al clickear con el botón derecho en la sección en la que acaba de
modificar ese texto.
Para crear un nuevo método, debe seleccionar la categoría all de la sección de
categorías de métodos. De esa forma verá un esqueleto de método que deberá
completar como corresponda. Para nuestro ejemplo, crearemos el método Inicializar
reemplazando el texto:
message selector and argument names
"comment stating purpose of message"
| temporary variable names |
statements
por el texto:
inicializar
"metodo de inicializacion de una instancia de la clase pila"
Tope:=0.
cantMax:=10.
Elemento:= Array new: 10.
Para guardar esta nueva definición clickee nuevamente con el botón derecho y
seleccione accept. Asegúrese de haber creado este método como método de instancia.
Para esto debe estar clickeada la opción Instance debajo de la sección de clases.
Los restantes métodos de la clase Pila son:
Métodos de Clase
new
^(super new) inicializar
Métodos de Instancia
estaVacia
^(tope = 0)
estaLlena
^(tope = cantMax)
apilar: unElem
self estaLlena
ifTrue: [self error: ‘pila llena’]
ifFalse: [tope := tope + 1.
elementos at:tope put:unElem]
desapilar
| temp |
(self estaVacia)
ifTrue: [self error: ‘pila vacia’]
ifFalse:[temp := elementos at: tope.
tope := tope - 1. temp]
error: string
string printString
Al terminar de crear la clase o en cualquier paso intermedio recuerde grabar la
imagen de Squeak para que cuando vuelva a ejecutar el programa se mantengan los
cambios que realizó en el ambiente. Para esto debe acceder al menú World y elegir la
opción Save. Cuando termine de trabajar con Squeak Smalltalk elija la opción Save and
Quit del menú World.
SOBRE LA REDEFINICIÓN DEL MÉTODO NEW Y LA PSEUDO VARIABLE SUPER
En la clase Pila mostrada arriba el método de clase new fue redefinido con el fin de que
toda nueva instancia de la clase esté inicializada al momento de su creación. Para ello
fue necesario emplear la variable especial super. La variable self permite que un objeto
pueda referenciarse a sí mismo. Sin embargo, super hace referencia al alcance de la
superclase correspondiente. Luego, super permite saltear un nivel en la cadena de
herencia. De este modo, cuando en el cuerpo del método se incluye la sentencia super
new, este último new refiere al definido en la clase Object. De otra forma, la
redefinición de new sería recursiva y su cómputo nunca finalizaría. Esta característica
es muy útil cuando se desea inicializar los objetos recién creados.
2.7. HERENCIA
Smalltalk implementa la herencia en el sentido introducido anteriormente. Una
subclase hereda el comportamiento de la superclase. Cuando un método es invocado se
inicia una búsqueda a lo largo de la cadena de clases vinculadas por esta relación, hasta
finalizar en la clase Object que es la raíz de la estructura de clases predefinidas.
La herencia simple establece una jerarquía en forma de árbol. Esto significa que
cada clase tiene a lo sumo una superclase, aunque puede tener varias subclases. En la
raíz de la jerarquía se encuentra la clase Object. Todas las clases, excepto Object, tienen
exactamente una superclase. También decimos que Object constituye la metaclase de
Smalltalk. Es decir la clase de la que derivan todas las clases.
Una subclase hereda variables y métodos de su superclase. De este modo, las
variables y métodos de instancia de la superclase se convierten automáticamente en
variables y métodos de instancia de la subclase.
Además de las variables heredadas, una subclase puede declarar nuevas variables
de instancia. Los métodos de una subclase invalidan a los métodos heredados con igual
nombre. Hemos dicho antes que un método es la implementación de una operación.
Suponga que para alguna operación con nombre op, tanto la superclase como la
subclase implementan métodos. En este caso, decimos que la subclase redefine el
método de su superclase. Luego, los objetos que sean instancia de la subclase utilizan la
implementación proporcionada por la subclase. Una excepción a esto lo constituye el
uso de la variable super.
En resumen, una clase tiene una superclase ‘inmediata’ y posiblemente una o más
subclases, con la clase Object en la cima de la jerarquía. Las clases situadas más arriba
en la jerarquía representan características más generales, mientras que clases más
abajo en la jerarquía representan características más específicas (relación is-a). Un
objeto hereda todas las variables de instancia definidas en sus superclases más las
contenidas en su propia clase. Los métodos también se heredan. Cuando se envía un
mensaje a un objeto, Smalltalk busca el método correspondiente en la clase del objeto.
Si lo encuentra, lo ejecuta. En caso contrario, repite el procedimiento en la superclase
del objeto. Este proceso continua hasta llegar a la clase Object. Si no se encuentra el
método se produce un error.
Descargar