Referencia dinámica a tipos de clase en Java

Necesitaba aplicar una serie de operaciones en distintos tipos de datos que comparten ciertas características. Hice lo lógico: creé una clase abstracta que implementa las funciones básicas de las características en común e hice que las demás clases fueran subclases de ella.

public abstract class BaseClass {

   // Propiedades y métodos comunes implementados aquí

}
public class SubClass1 extends BaseClass  {

   // Propiedades y métodos exclusivos
}
public class SubClass2 extends BaseClass {

    // Propiedades y métodos exclusivos
}

En los métodos que aplican las operaciones en cuestión declaré como parámetro la super clase (la abstracta) para que pudiera recibir cualquier subclase. El código quedó más o menos así.

public PriorityQueue<BaseClass> operation1 (List<? extends BaseClass> list) {
    // Hacer algo con los elementos en la lista
}

Hasta aquí todo bien.

El problema surgió cuando dentro de una de las operaciones tenía que modificar varias propiedades comunes de los objetos incluidos en la lista. Debido a la forma en la que Java pasa los parámetros (por valor,  aunque los objetos siempre pasan por referencia. Ver aquí), modificar en el método una de las propiedades del objeto no serviría de nada. Lo primero que se me vino a la mente fue crear clones de los objetos de la lista, pero muchos dicen que hay que evitarlos en la medida de lo posible, en especial cuando se tiene una estructura de clases compleja y algunos objetos no implementan la interface Clonable.

Ya he trabajado con clones antes y no hubo mucho problema. Sin embargo, quería ver si podía aplicar la solución de crear copy constructors para cada clase en la estructura y llamarlos dinámicamente. El problema es que necesitaba saber en tiempo real a qué clase pertenecían los objetos en la lista. Cierto: puedo hacer una serie de if con instanceof para probar cada una de las clases, pero se me hacía que había una mejor solución. Un simple:

BaseClass copy = new BaseClass(originalobject)

está fuera de contexto porque la clase base es abstracta (no se puede instanciar directamente).

La solución es relativamente sencilla: después de crear el copy constructor y de llamar en él al copy constructor de la superclase, en las operaciones tomo la clase de los elementos de la lista y creo dinámicamente una instancia de su copy constructor, la cual puedo llamar para crear una nueva instancia de la clase que contendrá los elementos del objeto original más lo que haya necesitado modificar. Al final meto todo en una cola que se ordena solita (basada en el compare de la clase) y es lo que regreso.

Los métodos que se usan:

  • Object.getClass() : para obtener en tiempo real la clase del objeto en cuestión.
  • Class.getDeclaredConstructor(Class) : para obtener el constructor que reciba los parámetros indicados. Como en este caso se trata de copy constructors, el único parámetro es un objeto de la misma clase, determinado con el getClass().
  • Constructor.newInstance(Object): para obtener una nueva instancia de la clase. En este caso, el constructor debe recibir como parámetro un objeto de la clase BaseClass o alguna de sus subclases.

Algo más o menos así:

public abstract class BaseClass {

   protected BaseClass() {
      // Inicialización de propiedades en común
   }

   // Copy Constructor
   protected BaseClass (BaseClass bc) {
       // copiar los datos de bc a esta instancia
   }

}

public class SubClass1 extends BaseClass {

    public SubClass1 {
       super();
       // Inicialización de propiedades exclusivas
    }

    // Copy Constructor
    public SubClass1 (SubClass1 sc1) {
        super(sc1);
        // Copiar los datos exclusivos de sc1 a esta instancia
    }
}

public class SubClass2 extends BaseClass {

    public SubClass2 {
       super();
       // Inicialización de propiedades exclusivas
    }

    // Copy Constructor
    public SubClass2 (SubClass2 sc2) {
        super(sc2);
        // Copiar los datos exclusivos de sc2 a esta instancia
    }
}

Y las operaciones:

public PriorityQueue<BaseClass> operation1 (List<? extends Searchable> list) {

    Class<? extends BaseClass> objclass = null;
    Constructor<? extends BaseClass> theConstructor = null;
    BaseClass newElement = null;

    for (BaseClass bc : list) {
       // Hacer algo con los datos

      objclass = bc.getClass();
      theConstructor = objclass.getDeclaredConstructor(objclass);
      newElement = theConstructor.newInstance(bc);

       // Hacer las operaciones restantes, crear la cola y devolverla
    }
}

Una alternativa más para la referencia dinámica a las clases y sus constructores.

Plugin de Veetle 64 bits

Muy de vez en cuando quiero ver un video o transmisión en vivo que necesita el plugin de veetle, pero el download que viene por default en la página de descargas es para arquitecturas de 32 bits. Intenté instalarlo con ndiswrapper, pero aun así no funcionaba.

Buscando en internet, me encontré que veetle también tiene plugin para arquitecturas de 64 bits, pero no está fácil encontrarlo. Por acá la liga:

http://veetle.com/download.php/veetle-0.9.17plus-linux-install.sh

Instálenlo como usuario normal. Lo que hace es copiar los plugins necesarios al directorio ~/.mozilla/plugins

Listo. VeetleTV funcionando en 64 bits. Rara vez lo uso, pero nunca está de más tenerlo.

Cabe mencionar que vlc también puede reproducir y grabar streams de Veetle. Hay muchos tutoriales en internet, por ejemplo:

http://netimports.blogspot.com/2010/10/how-to-record-watch-veetle-broadcasts.html

Queda para el registro 🙂

Los años maravillosos – Parte 5

A estas alturas creo que no se necesita introducción, ¿verdad? Agarren palomitas, refresco y pónganse muy cómodos, porque creo que ahora sí me extendí.

Si es la primera vez que leen un escrito de esta serie, por acá pueden leer las entregas pasadas:

Ingeniero – Parte 3

Desde octubre de 2001 estuve sin trabajo, buscando a ver en dónde podría conseguir algo. Justo a principios de año (2002), Omar me dijo que la empresa donde laboraba estaba buscando contratar gente. Omar me recomendó, me hicieron entrevista y, de forma por demás rápida, ya tenía trabajo.

La empresa ya tenía planeado en qué proyecto iba a participar, pero para ello necesitaba estudiar una tecnología llamada COM, la cual utilizaría en el trabajo que se me iba a asignar… o al menos ésa era la idea.

Entré a trabajar en un proyecto dentro de Hewlett-Packard Guadalajara, pero los administradores de proyecto estaban en Boise, Idaho, por lo que la comunicación sería totalmente en inglés. Además, mi lugar de trabajo serían las oficinas de HP. Me tenía que levantar más temprano, haría más tiempo en los camiones, pero no importaba; el trabajo era bueno, se veía interesante y parecía que podría crecer profesionalmente.

Algo curioso de este trabajo fue que, por primera vez desde que egresamos de la universidad, Omar y yo estábamos en el mismo lugar (mismas oficinas), pero trabajando en proyectos diferentes.

No pasaron más de 2 meses desde que entré cuando me enviaron a Idaho, a la planta de HP, para entrenamiento. Estuve por allá 3 semanas, viviendo en medio de nieve, frío… Big Brother y un trabajo que no tenía nada que ver con lo que me habían dicho que haría.

Enfado

Creo que no es apropiado contar punto por punto lo que viví en Idaho en lo que respecta a la vida fuera del trabajo. Lo que sí es preciso mencionar es que la empresa quería ahorrarse dinero a toda costa y no le importaba sacrificar la comodidad de sus empleados con tal de que no se gastara tanto.

El trabajo no era nada de lo que me habían dicho que era. Lo que había estudiado solamente sirvió para entender lo que internamente se usaba, pero nunca me tocó jugar con eso. En vez de programar, seríamos prácticamente testers (personas que se dedican a hacer pruebas de algo que ya está terminado, y en muy remotoso casos se le puede meter mano al código). Yo me quejé con mi jefa de México creo que al segundo o tercer día de estar allá, pero la respuesta que recibí fue que conforme el proyecto avanzara iba a tener oportunidad de programar, cosa que era totalmente diferente a lo que habían mencionado al principio.

Las 3 semanas pasaron. Aprendimos lo que había que aprender y regresamos a Guadalajara. Mi jefe inmediato (un ingeniero en electrónica) sugirió que nos dividiéramos el trabajo, ya que eran 4 proyectos y lo conveniente sería que cada uno estuviera a cargo de 2. Yo le di prioridad a él y lo dejé que escogiera, y me quedé con los 2 proyectos restantes. Mi jefe en Idaho resultó ser una persona muy inteligente, muy sociable, muy amable y muy comprensivo; mi trabajo se convirtió en algo realmente sencillo, pues los 2 proyectos que tenía asignados para estar probando rara vez daban problemas. Y no exagero: había días en que llegaba y en 3 horas terminaba el trabajo, por lo que me desocupaba temprano y me quedaba mucho tiempo libre. Pero no puedo mencionar lo mismo sobre mi jefe inmediato: tenía muchos problemas con un proyecto, y no le daba tiempo de atender otro, por lo que me lo asignó voluntariamente a fuerzas. Quedamos 3-1, y no precisamente en un marcador en el que me hubiera gustado ganar. Pero incluso así, yo sacaba el trabajo de las pruebas de 3 proyectos sin muchos problemas mientras él le sufría con el otro (que él mismo escogió).

Lo anterior puede sonar divertido, pero realmente no lo era. Quizá lo que más disfrutaba del trabajo era la cotorreada con los compañeros. Nos poníamos a jugar Magic a la hora de la comida, platicábamos, criticábamos, sufríamos los estragos de la empresa. El ambiente era genial, y conocí gente muy talentosa, entre ella a un chavo que es (y desde entonces lo era) una eminencia en programación en Windows, al grado que fue contratado por Microsoft y terminó yéndose a residir a Redmond, y hasta la fecha aún está por allá.

Me tocó regresar a Idaho varios meses después, en verano (la primera vez fui en invierno y conocí lo que era el frío verdadero). Boise, la capital, es un lugar muy bonito y muy campirano. De hecho, broméabamos diciendo que la mitad de la gente que vive en Boise trabaja para HP y la otra mitad trabaja para la gente que trabaja para HP. Eso sí: las baked potatoes son deliciosas. Pero desde antes de volver a Idaho, yo me quejaba y buscaba la forma de salirme de ese proyecto y que me asignaran otro. El ambiente de trabajo era bueno y la paga no era mala, por lo que nunca me pasó por la mente renunciar. Lo único que me haría salirme de ese trabajo sería que me dieran la beca a Japón, en cuyo caso renunciaría no por gusto, sino porque la ida a Japón era mucho más importante… y de hecho casi sucedió así, y los detalles de mi renuncia los pueden leer por acá. Por cierto, ahora que vuelvo a leer eso que escribí hace 6 años y comparándolo con mi estado actual, he comprendido mucho más el móvil de las empresas respecto al trato a sus empleados.

He de recalcar que no odié (ni odio) a nadie de esa compañía. Mi jefe inmediato le echaba ganas, y mi jefa pues… actuaba porque así tenía que actuar. Por ahí me habían dicho que la empresa había quebrado, pero echándole un vistazo a internet parece que todavía anda por ahí, lo cual me da mucho gusto. Ojalá que sigan echándole ganas, y que en todos estos años haya mejorado el trato y la relación con los empleados.