Hola. Hoy vamos a examinar una sutileza muy interesante
que puedes aplicar en sus programas.
Para comenzar, revisaremos rápidamente el programa de dados
Si recuerdas, en este ejercicio definimos la clase Dice
para definir instancias de esta clase y representan varias caras de dados.
Definimos una clase llamada DiceHandle.
Luego implementamos el método "plus"
en la clase DiceHandle,
para agregar DiceHandles y construir un nuevo DiceHandle.
Este es el código para esta clase.
Tenemos DiceHandle new.
Creamos un nuevo DiceHandle,
al que agregamos los dados de la clase receptora
y la configuración,
y devolvemos este handle al final del método. ¿Bueno?
En esta secuencia veremos la diferencia,
en este método "+", entre escribir DiceHandle new
y self class new.
Y veremos por qué. una técnica es mejor.
Este es el problema.
Si creo una subclase DiceHandle llamada MemoDiceHandle,
y quiero agregar MemoDiceHandles,
con el método "+" que se hereda de DiceHandle,
el resultado es una instancia de la clase DiceHandle.
No de la clase MemoDiceHandle.
Esto es un problema porque cuando agregamos elementos,
queremos obtener el mismo tipo de elemento de nuevo.
¿Cómo lo hacemos?
Solución N° 1.
Cambio la implementación
del método "+" en la clase DiceHandle.
El método "+", ¿de acuerdo?
Y simplemente agrego este método: self handleClass.
En lugar de definir la variable de instancia que deseo obtener,
uso un método que llamo handleClass.
En DiceHandle, se devuelve la clase DiceHandle,
y en la subclase MemoDiceHandle, se devuelve MemoDiceHandle.
Entonces simplemente redefiniendo el método handleClass,
obtenemos la instancia correcta cuando agregamos elementos.
Si ejecutamos el mismo código,
usando MemoDiceHandle en su lugar, obtenemos una instancia de MemoDiceHandle,
porque redefiní el método handleClass
en la clase MemoDiceHandle. Tenemos una instancia de la subclase.
Entonces alcanzamos nuestro objetivo.
El problema es que
cada vez que agregamos una subclase a DiceHandle,
debemos redefinir el método handleClass.
Si no lo haces, el método "+" nunca devuelve la instancia de clase correcta.
Esto es tedioso. Debes constantemente redefinir el método.
Hay formas mejores.
Aquí está la solución N° 2.
Usando el método "+" en DiceHandle, esta vez escribiremos:
self class new.
Le preguntaré al receptor actual por su clase,
para obtener una instancia.
De hecho, la self class siempre retorna la clase del receptor.
Si es la instancia de una subclase,
devolverá la clase correcta. Por ejemplo, MemoDiceHandle.
Obtenemos instancias del mismo tipo del receptor.
Como conclusión,
como viste,
cuando envíe el mensaje "+" a un DiceHandle,
si fijas el nombre de la clase que quieres para una instancia,
en cierto sentido te previenes a ti mismo de la creación de subclases.
Pero con self class new, "+" retorna una instancia del receptor.
De la subclase potencial.
Entonces es mucho mejor usar self class new,
para obtener directamente
una instancia de la clase de acuerdo al tipo de receptor.