Hola a todos, este video muestra algunos temas avanzados sobre las clases.
Tiene tres partes principales.
En primer lugar, cómo compartir estado entre instancias de una clase y sus subclases.
En segundo lugar, cómo hacer que las clases tengan sus propias variables.
En tercer lugar, cómo inicializar las clases.
Primero, cómo compartir estado entre instancias.
Aquí tenemos una clase con varias instancias.
Para compartir estado, estas instancias requieren un objeto común.
En Java, usamos una variable de "instancia" con el keyword "static".
El valor de una variable estática
es el mismo para todas las instancias.
En Pharo, usamos "variables de clase".
Esta debería ser una expresión familiar que nos permite crear clases.
Aquí creamos la clase "Color", que es una subclase de "Object".
Primero, enumeramos sus variables de instancia, echemos un vistazo a la siguiente línea.
Enumera las variables de clase de la clase Color.
La clase "Color" tiene al menos dos variables, ColorRegistry y ComponentMask.
Los valores de una variable de clase
se comparten entre todas las instancias de la clase y las subclases.
Estas variables son accesibles desde métodos de instancia y clase.
Comienzan con una letra mayúscula.
Volvamos a nuestro ejemplo.
Aquí tenemos nuestra clase "Color",
que es una instancia de la metaclase "Color class".
La clase Color define dos variables estándar, "rgb" y "alpha".
Estas variables de instancia son privadas,
lo que significa que solo son accesibles utilizando los métodos de la clase Color.
También define ColorRegistry, que está subrayado y en mayúsculas.
Esto indica que esta variable está compartida.
Es una variable de clase que es accesible
por los métodos de la clase "Color" y los de la clase "Color class".
Aquí hay unos ejemplos de los usos de esta variable.
En un método de instancia, "privateBlue" en la clase "Color",
accedemos a la variable de clase usando su nombre.
Del mismo modo, si queremos asignarle a esta variable un valor,
usamos " := " como con cualquier variable.
Podemos hacer esto en el lado de la instancia o de la clase.
Muy a menudo,
los valores de estas variables de clase se acceden
desde los métodos de instancia,
y se escriben desde los métodos de clase.
Esto es lo que ocurre con mayor frecuencia, no es obligatorio.
Ahora veamos variables de instancia de clases.
No es lo mismo.
Una clase es un objeto, como todo.
Como todos los objetos, una clase puede tener instancias.
La metaclase describe la clase y enumera las variables de instancia
que solo se puede acceder por su única instancia, su clase.
Para definir una variable de instancia en el lado de la clase,
hacemos clic en el botón "class" en el navegador de código.
Eso nos da la expresión aquí.
Entonces, ahora estoy navegando la clase RPackageSet.
La metaclase de esta clase define una variable denominada cachePackages.
Estas variables solo se pueden acceder de los métodos de clase
y siempre comienzan con una letra minúscula.
Aquí hay un ejemplo.
La variable cachePackages se define en la metaclase "RPackageSet class".
Esto significa que
la clase RPackageSet, que es una instancia de la metaclase,
tiene un valor asociado con esta variable.
Similarmente,
todas las instancias de las subclases de la clase RPackageSet
tienen un valor específico para esa variable, que es un valor diferente.
No se puede compartir aquí.
Cada instancia de la clase RPackageSet o sus subclases
tiene su propio valor para esta variable.
Las variables de clase y variables de instancia en el lado de la clase son cosas diferentes.
Explicaremos esto usando el patrón de diseño Singleton,
cuyo objetivo es garantizar que una clase tiene solo una instancia.
Una solución para ejecutar este patrón es almacenar, dentro de una variable,
la instancia que es de libre acceso y deshabilitar la creación de una nueva instancia.
Eso es lo que haremos aquí con WebServer.
Aquí utilizamos una variable de instancia en el lado de la clase.
Su nombre es en minúsculas.
Esta variable se define en la definición de la metaclase.
Ahora deshabilitamos la ejecución del método "new".
No se pueden enviar mensajes a Clase WebServer para crear nuevas instancias.
Es imperativo ir a través de uniqueInstance,
que devuelve el valor de la variable si no es nada y tiene contenido,
o bien agrega algo a la variable usando "super new".
Crea una nueva instancia de la clase WebServer,
y la almacena en la variable uniqueInstance.
El hecho de que usemos variables de instancia de clase
conduce al siguiente resultado.
Cada subclase de la clase WebServer
tendrá su propio valor
para una instancia única.
Entonces, si WebServer tiene tres subclases,
la variable uniqueInstance Tendrá un total de cuatro valores.
Uno para WebServer y otro para cada subclase.
Si ahora usamos una variable de clase,
editamos la clase en el lado de la instancia
y agregamos UniqueInstance, usando una U mayúscula.
Nuevamente rechazamos el envío del mensaje "new" e implementamos UniqueInstance.
La unica diferencia es que usamos una U mayúscula.
Como resultado de elegir una variable de clase,
la jerarquía de clase tiene solo un singleton.
Si WebServer tiene tres subclases,
estas tres subclases y WebServer comparten el mismo singleton.
Por lo tanto, tenemos una instancia compartida por todos.
Ahora para la inicialización de clases.
Podemos tener variables compartidas entre una clase y sus instancias,
pero en algun momento debemos darles un valor.
Hacemos esto cuando inicializamos la clase.
Los objetos se inicializan cuando se envía el mensaje "initialize".
Del mismo modo, podemos enviar el mensaje "initialize" a una clase.
Decidimos cómo inicializar variables usando el código del método de inicialización.
Si queremos inicializar la clase Color,
le enviamos el mensaje de inicialización.
Típicamente, cuando una clase se carga en el sistema
por la herramienta de control de versiones,
el mensaje de inicialización se envía a todas las clases.
Esto es automático, no hay necesidad de enviar el mensaje
manualmente a todas las clases cargadas.
Pero si implementamos una clase,
si creamos una nueva clase usando el método "initialize"
debemos enviar el mensaje manualmente.
Aquí hay un ejemplo en la clase Color.
Podemos ver que estamos en el lado de la metaclase.
Aquí inicializamos varias variables de clase,
o variables de instancia en el lado de la clase.
Hay de los dos tipos de variables aquí.
En los métodos de inicialización,
nunca usamos "super initialize" en el lado de la clase.
Cuando agregamos un método de inicialización por el lado de la instancia,
nosotros llamamos sistemáticamente "super initialize"
para inicializar todas las variables de instancia de un objeto recién creado.
Pero para las clases,
ya que existen clases y superclases cuando se envía el mensaje de inicialización,
no enviamos "super initialize" en el método de inicialización
en el lado de la clase para evitar reiniciar las clases.
Este es el resumen.
Utilizamos las variables de clase para compartir estado.
Las clases son objetos que puede tener sus propias variables,
entonces usamos variables de instancia en el lado de la clase.
Para inicializar una clase, le enviamos un mensaje de inicialización
y aplicar el método "initialize" en el lado de la clase.