Implementando la carga dinámica de clases en Processing

Introducción

La carga dinámica de clases es una característica muy conocida de los lenguajes orientados a objetos que permite crear instancias de clases con solo conocer su nombre.  Esto permite a los desarrolladores crear aplicaciones que utilicen clases que sean creadas después de la aplicación sin necesidad de recompilar la misma.  También es muy útil cuando se desea generalizar la creación de un conjunto de objetos mediante el patrón de fábrica.

Gracias a la reflexión en Java y otros lenguajes como C# es muy fácil de implementar, sin embargo en Processing (derivado de Java) su implementación fue un poco mas elaborada ya que las clases que implementa el usuario son en realidad clases internas del proyecto desarrollado.

Explicación

En Processing cuando se crea un Proyecto y en él se implementan las clases A, B y C, y este se compila, internamente se crea un archivo de código fuente Java conteniendo a este código de la siguiente manera.

import processing.core.*;

// Imports del usuario

// Otros imports

public class Proyecto extends PApplet {

    class A
    {
        // ...
    }

    class B
    {
        // ...
    }

    class C
    {
        // ...
    }

    static public void main(String args[]) {
        PApplet.main(new String[] { "--bgcolor=#DFDFDF", "Proyecto" });
    }
}

Implementación

Para realizar la implementación de una versión simple del patrón de fábrica utilizando la carga dinámica de clases en Processing se supondrá que existe la clase Padre de la cual se derivan las clases Hijo1 e Hijo2 del proyecto Demostracion.

Crear un objeto donde se almacenará la instancia a crearse de manera dinámica.

Padre instance = null;

Recuperar la referencia al cargador de clases del sistema.

ClassLoader classLoader = ClassLoader.getSystemClassLoader();

Cargar la referencia de la clase a partir de su nombre (className), en este caso podría ser Hijo1 o Hijo2.  Recuerde que esta clase es realmente interna a la clase Demostracion.

Class loadedClass = classLoader.loadClass("Demostracion$" + className);

Obtener una referencia al constructor que se desea utilizar para crear la instancia.  En este caso se eligió un constructor que recibe dos parámetros: una cadena y un real.  Nótese además que todos los constructores reciben una referencia al applet de Processing, en este caso de Demostracion (que hereda a su vez de PApplet).

java.lang.reflect.Constructor constructor = loadedClass.getConstructor(new Class[] {PApplet.class, String.class, float.class});

Crear la nueva instancia utilizando el constructor obtenido en el paso anterior.  Al método newInstance se le especifican los valores de los parámetros que serán suplidos en el constructor.

instance = (Padre) constructor.newInstance(new Object[] {applet, str, flt});

Nótese como el primero de ellos, applet, hace referencia al applet de Processing que se está ejecutando.  Al no encontrar una forma mas elegante para obtener esta referencia al applet, declarar una variable global para almacenarlo.

PApplet applet;

Y obtener su valor en el procedimiento setup.

void setup()
{
    // ...

    applet = this;

    // ...
}

En el código mostrado anteriormente se deberán manejar las excepciones ClassNotFoundException y ClassCastException para poder llevar a feliz término su ejecución.

Enlaces

Leave a Reply

Your email address will not be published. Required fields are marked *