2009-11-10 17 views
6

Lo que me gustaría hacer es cargar un conjunto de clases, probablemente todas en la misma carpeta. Todos ellos implementan la misma interfaz y son de la misma clase, luego en mi código me gustaría poder llamar funciones en esas clases.Java: cargar dinámicamente varias versiones de la misma clase

+0

Esto no es posible sin jugar juegos con la costumbre cargadores de clases (y tal vez ni siquiera sea posible en ese momento). Tal vez si explicaras lo que estás tratando de lograr obtendrías más ayuda. –

+0

OSGI parece muy interesante, sin embargo, tal vez me estoy acercando a este problema incorrectamente. En un sentido menos genérico, esto es lo que estoy tratando de lograr. Tengo un shell del juego Oware que ejecuta la mecánica del juego. Pide a otras clases que realicen sus movimientos enviándoles el estado del juego y devolviendo un movimiento. Me gustaría tener una carpeta de AIs cada una que contenga un código diferente, podría haber muchas de ellas. El caparazón ejecutará un torneo round robin en todas las IA que encuentre y genere las IA ganadas. – JonLeah

Respuesta

5

Sobre la base de su respuesta a mi pregunta, parece que desea definir una interfaz de juego y luego enchufe en cualquier número de implementaciones de AI, probablemente configuradas a partir de un archivo .properties. Este es un uso bastante estándar de una interfaz API.

Defina una EngineInterface que proporcione un método que acepte el estado del juego y devuelva el movimiento. Luego define múltiples clases que implementan EngineInterface. El controlador lee un archivo de propiedad para obtener los nombres de las clases de implementación, los crea una instancia con Class.forName() y los almacena en una lista y/o mapa. Luego, cuando el conductor recibe las solicitudes, invoca cada implementación por turno y realiza un seguimiento de los resultados.

1
  1. Si puede utilizar OSGi, su tan simple como romperse un dedo! En oSGI puede tener varias versiones de la misma clase . Todo lo que debes hacer es tener los mismos paquetes con diferentes versiones.

  2. De lo contrario, aún puede escribir su cargador de clases personalizado que lea ambas clases. Una forma de hacerlo sería así. Usted escribe dos ClassLoaders, uno de ellos carga una versión de la clase y el otro carga la otra versión de la clase. Ahora, según la necesidad, elija classloader1 o classloader2 para cargar la clase. Entonces ahora también puede tener múltiples versiones de la misma clase cargadas simultáneamente en la memoria.

Nota: Asegúrese de que esto es en realidad que quiere hacer, pueden existir otras formas de llegar alrededor de su problema.

+0

puedo tener osgi? –

+0

@jason ... no te entendí :) –

+5

"tan simple como chasquear un dedo" ... Esa es una afirmación audaz con respecto a OSGi. – Thilo

1

El único marco que sé que no apoya lo que está después es OSGI:

alt text http://blog.springsource.com/wp-content/uploads/2009/01/network.png

Su modelo de red, que se describe en este artículo "Exposing the boot classpath in OSGi", sí permite que

Uno de los efectos secundarios (u objetivos) del modelo de red es el aislamiento de tipo o el control de versiones de clase: la versión múltiple de la misma clase puede coexistir muy bien dentro de la misma máquina virtual ya que ch one se carga en su propia red, su propio espacio.

ver este tutorial de inicio y elija un EOF la infraestructura OSGi (como Equinox, Knoplerfish o Apache Felix)

2

Ha intentado algo así como:

class Move; // some data type that is able to represent the AI's move. 

interface AI { 

    Move getMove(GameState state); 
}; 

AIOne implements AI; 
AITwo implements AI; 

Cada clase sería implementar su propio algoritmo para generar un movimiento, sino que serían los llamados y llamados por método común

2

Es posible hacer lo que quiera con OSGI pero también podrías usar un cargador de clases personalizado. La idea es que debes instanciar un cargador de clases para cada versión de la clase que quieras cargar.Here puede encontrar una buena explicación.

Pero creo que lo que realmente necesita para resolver su problema es algo basado en interfaces como se describe por Jim Garrison o de Dave L Delaney ...

0

Se puede hacer uso de carga dinámica de clases. No está cargando clases de versiones diferentes sino diferentes subclases de una súper clase o interfaz.

Los pasos importantes son:

(1) Uso Class.forName (...) para cargar una clase por su nombre. La clase debe estar en la ruta de clase.

(2) Use aClass.newInstance() para crear una instancia del objeto. Esto es fácil si no se necesita ningún parámetro para el constructor.

El siguiente código debería proporcionarle alguna idea. No maneja la excepción que tienes que hacer.

class Context { 
    void moveUp(); 
    void moveDown(); 
    ... 
} 

interface AI { 
    void action(Context con); 
} 

public class Game { 
    public Game() { 
     Context aContext = new Context(); 
     String[] aAIClsNames = this.getAIClassNames("ai.list"); 
     AI[]  aAIs  = this.loadAI(aAIClsNames); 
     this.run(aAIs); 
    } 
    String[] getAIClassNames(String pAIClassListFile) { 
     // .. Load the file containning the AI-class file names 
    } 
    AI[] loadAI(String[] pAIClsNames) { 
     AI[] AIs = new AI[pAIClsNames.length]; 
     for(int i = 0; i < pAIClsNames.length; i++) { 
      String aAIClsName  = pAIClsNames[i]; 

      // (1) Get the class by name 
      Class<? extends AI> aAICls = Class.forName(aAIClsName); 

      // (2) Notice the cast as all of class in the list must implements AI 
      AIs[i] = (AI)aAICls.newInstance(); 
     } 
     return AIs; 
    } 
    void run(AI[] pAIs) { 
     // ... 
    } 
} 

Espero que esto ayude.

0

La respuesta de Jim es buena: usted nombra las clases que desea usar, y todas se ajustan a una API común. Sin embargo, la solución dada supone que todas las clases ya están disponibles en el classpath de la aplicación. Es posible que desee agregar más implementaciones más tarde, p. después de que la aplicación está instalada.

Si ese es el caso, entonces es probable que necesite utilizar un cargador de clases personalizado. Por ejemplo, podría permitir que las personas coloquen archivos jar dentro de una carpeta particular en alguna parte, y agregar los nombres de clase de las implementaciones a un archivo de propiedades. Entonces necesitarías un cargador de clases personalizado que pueda cargar clases desde los archivos dentro de esa carpeta, y usarías ese cargador de clases para cargar las clases (por ejemplo, usando Class.forName (className, classLoader)).

De hecho, si tiene un cargador de clases por archivo jar, podrá tener varias clases con los mismos nombres en los archivos jar, ya que el cargador de clases define los límites del nombre de clase. Esto es más o menos lo que OSGI está haciendo.

Aquí hay un código relativo a cargar las clases de los frascos:

http://sourceforge.net/projects/jcloader/ http://www.javaworld.com/javatips/jw-javatip70.html

Cuestiones relacionadas