Buenos días a todos. En esta tercera secuencia, despues de
interesarnos por la herencia, self y la búsqueda (lookup), vamos a
interesarnos por super.
En esta secuencia, nos interesaremos
particularmente por el envío de mensajes cuando super es el receptor.
¿Entonces que es super?
Tomaros unos minutos para plantearos la pregunta y
en todo caso responder a estas 2 preguntas.
Que representa super?
Como funciona el envío de mensajes cuando super es el receptor?
Lo que os voy a decir aquí, es igual tanto en Pharo como en Java.
En este ejemplo, que se parece a los ejemplos vistos
en la secuencia anterior, utilizamos super en uno de los métodos.
Intentaremos pensar un poco en que es lo que ocurre.
Para A new bar, ninguna dificultad, como
en el ejemplo anterior.
Este método bar es ejecutado y Foo devuelve 10.
En el caso de B new bar, lo haremos etapa por
etapa. envíamos el mensaje bar al objeto B new.
El algoritmo de lookup busca un método
bar a partir de la clase de este objeto.
Ha encontrado el método bar, que se ejecuta
en el receptor. Así es este método bar, aquí, el que
se ejecutara en el receptor.
Ahora es necesario calcular super bar, self foo y
que haga la suma de los dos.
Podemos hacer self foo.
Self foo envía el mensaje foo al objeto self.
Self, es mi B new.
Solo hay un foo posible, es aquel que se encuentra en la clase A.
Self foo devuelve 10.
Super bar : super, es el
receptor. Así que, el algoritmo de búsqueda cambia
en presencia del receptor super.
Buscaremos el método bar a partir de la super clase
de donde se encuentre la palabra clave super.
Super se encuentra en el método bar de la clase B, así que
buscaremos un método bar a partir de la super
clase de B, es decir A.
Encontramos este método y es este método el que sera ejecutado.
Así que foo se envía a self.
Self, es siempre el objeto mismo, es siempre el receptor, es B new.
Foo es así envíado al objeto inicial así pues es este
foo aquí él que sera ejecutado y devuelve 10.
10 y 10 : 20.
En el caso de C new bar, tenemos nuestro C new que esta aquí
y que es una instancia de la clase C y le envíamos el mensaje bar.
Bar se busca en la clase de C new, es decir C.
No lo encuentra aquí, lo busca debajo.
Lo encuentra aquí, es pues esta bar el que se ejecutara.
Este bar es la suma de 2 envíos de mensajes.
Podemos empezar por el segundo una vez mas, envíamos
el mensaje foo al objeto self.
Self, es siempre my C new que se encuentra aquí.
Envío el mensaje foo.
Encuentra este método.
Devuelve 50, aquí tengo 50.
Super bar, ahora nos falta la primera parte
de la suma de super bar.
Envío el mensaje bar a super.
Super, es siempre el receptor pero el algoritmo de
lookup cambia y buscara bar a partir de la super clase
del lugar donde se encuentra la expresión que contiene
super, es decir el método bar de la clase B, es decir
la clase B, así que empezamos a buscar ba a partir de
la super clase de B, es decir A.
Bar se encuentra aquí.
es este bar el que se ejecuta.
Self, es siempre C new, es siempre este,
siempre el receptor y le envíamos el mensaje foo.
Encontramos el 50. aquí tengo 50 : 50 y 50,
100.
En este slide, tenéis los detalles de la ejecución del algoritmo
para poder revisar y volver a trabajar este ejemplo.
Super esta referenciado siempre en el receptor, es exactamente
como self o como this en Java.
Y igualmente, super en Java, es como this en Java, esto
representa siempre el receptor.
Al contrario cuando un mensaje se envía a super, el algoritmo
de búsqueda cambia y empieza a buscar un método
a partir de la super clase, de la clase que contiene el
método a ejecutar en el lugar donde se encuentra super.
Así self y super tienen una diferencia fundamenta: self
es dinámico así que super es estático.
Que quiero decir con eso?
Quiero decir que cuando foo se envía a self, el
desarrollador no tiene ninguna idea del método foo que se ejecutara.
Puede ser el foo que se encuentra en la misma clase,
en una sublaclase existente o bien en una subclase de una subclase
creada por otro desarrollador antes de la ejecución del programa.
Así pues cuando el desarrollador del método bar escribe
self foo, no tiene ninguna idea del método foo que se ejecutara.
es especialmente practico, quiere decir que
los desarrolladores pueden crear nuevas subclase para cambiar
el comportamiento de la clase A.
Super, por contra, es estático.
Cuando el desarrollador escribe "Super foo",
Sabe que método foo sera ejecutado
cuando se ejecute el programa.
Así que escribiendo esto, sabe que sera este método foo, aquí,
el que se ejecutara.
Siempre, Super es estático, cuando se compila sabemos
que método se ejecutara.
Desgraciadamente, algunos libros se equivocan en la
definición de super y dan definiciónes que no tienen este sentido.
aquí una definición que encontramos en un libro y
esta definición, nos dice que super busca
el método. Así que cuando el algoritmo de búsqueda ve
un super buscara el método a partir de la super clase del receptor.
así que la super clase de la clase del receptor.
De hecho esta definición es falsa.
Si tomamos el ejemplo siguiente, si tomamos como
receptor AC, su clase es C.
La super clase del receptor es entonces C.
Y aquí, ejecuto esta parte
con la definición anterior y
que es falsa, enviaríamos el mensaje foo
a super, y el método foo que se ejecutaría, es el
método foo que se encuentra en la super clase de la
la clase del receptor, es decir este método foo aquí
que ejecutaría esto, que enviaría el mensaje foo a super, que
que ejecutaría esto, y ect.. Así pues vemos aquí que
entramos en un bucle infinito, esta claro que la definición es errónea
porque en la practica no entramos en un bucle infinito.
Este ejemplo funciona a la perfección.
Así que esta definición simplemente es falsa.
Lo que debéis recordar: Self representa siempre
el receptor igual que Super.
Y igual que This en Java, This y Super representan siempre el receptor.
Por contra, super cambia el algoritmo de búsqueda.
El algoritmo de búsqueda buscara el método
correspondiente a partir de la super clase de la clase
que contiene el método, que contiene la palabra clave Super.
Los Envíos de mensaje a Self son dinámicos, y podemos
utilizarlos como desarrolladores para extender el
comportamiento de una clase existente construyendo
una subclas que redefine un método.