Ce que j'aimerais pouvoir faire est de charger un ensemble de classes, probablement toutes dans le même dossier. Tous qui implémentent la même interface et sont de la même classe, alors dans mon code j'aimerais pouvoir appeler des fonctions sur ces classes.Java: Charger dynamiquement plusieurs versions de même classe
Répondre
En fonction de votre réponse à ma question, il semble que vous voulez définir une interface de jeu, puis brancher dans un nombre quelconque d'implémentations AI, probablement configurées à partir d'un fichier .properties. C'est une utilisation assez standard d'une interface API.
Vous définissez une EngineInterface fournissant une méthode qui accepte l'état du jeu et renvoie le mouvement. Ensuite, vous définissez plusieurs classes qui implémentent toutes EngineInterface. Votre pilote lit un fichier de propriétés pour obtenir les noms des classes d'implémentation, les instancie avec Class.forName() et les stocke dans une liste et/ou une carte. Ensuite, lorsque le pilote reçoit des requêtes, il appelle chaque implémentation à tour de rôle et conserve la trace des résultats.
Si vous pouvez utiliser OSGI, est aussi simple que claquant un doigt! Dans oSGI vous pouvez avoir plusieurs versions de la même classe . Tout ce que vous faites est d'avoir les mêmes bundles avec des versions différentes. Dans le cas contraire, vous pouvez toujours écrire votre chargeur de classe personnalisé qui lit les deux classes. Une façon de le faire serait comme ça. Vous écrivez deux ClassLoaders, l'un charge une version de la classe et l'autre charge l'autre version de la classe. Maintenant, en fonction du besoin, vous choisissez classloader1 ou classloader2 pour charger la classe. Alors maintenant vous pouvez également avoir plusieurs versions de la même classe chargées simultanément dans la mémoire.
Note: Assurez-vous que c'est en fait que vous voulez faire, il peut y avoir d'autres façons de venir autour de votre problème.
je peux a osgi? –
@ jason ... je ne vous ai pas eu :) –
"aussi simple que de claquer un doigt" ... C'est une déclaration audacieuse en ce qui concerne OSGi. – Thilo
Le seul cadre que je sais qui prend en charge ce que vous recherchez est-OSGI:
alt text http://blog.springsource.com/wp-content/uploads/2009/01/network.png
Son modèle de réseau, décrit dans cet article "Exposing the boot classpath in OSGi", ne permet que
L'un des effets secondaires (ou objectifs) du modèle de mise en réseau est l'isolation de type ou le versioning de classe: plusieurs versions de la même classe peuvent cohabiter L'un est chargé dans son propre réseau, son propre espace.
Voir ce tutorial pour commencer et choisissez sur EOF le cadre OSGI (comme Equinox, Knoplerfish ou Apache Felix)
Avez-vous essayé quelque chose comme:
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;
Chaque classe mettrait en œuvre son propre algorithme pour générer un mouvement, mais que l'on appellerait, mais appelé par la méthode commune
Il est possible de faire ce que vous voulez avec OSGI mais vous pouvez aussi bien utiliser un chargeur de classe personnalisé. L'idée est que vous devez instancier un chargeur de classe pour chaque version de la classe que vous voulez charger.Here vous pouvez trouver une bonne explication.
Mais je pense que ce que vous avez vraiment besoin pour résoudre votre problème est quelque chose basé sur des interfaces comme décrit par Jim Garrison ou Dave L Delaney ...
Il peut être fait en utilisant le chargement dynamique des classes. Il ne charge pas la classe de la version différente mais les différentes sous-classes d'une super classe ou d'une interface.
Les étapes importantes sont:
(1) Utilisation Class.forName (...) pour charger une classe par son nom. La classe doit être dans le chemin de la classe.
(2) Utilisez aClass.newInstance() pour instancier l'objet. C'est facile s'il n'y a pas de paramètre nécessaire pour le constructeur.
Le code suivant devrait vous donner une idée. Il ne gère pas l'exception que vous devez faire.
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) {
// ...
}
}
Espérons que cela aide.
La réponse de Jim est bonne - vous nommez les classes que vous voulez utiliser, et elles sont toutes conformes à une API commune. Cependant, la solution donnée suppose que les classes sont déjà disponibles sur le chemin de classe de l'application. Vous voudrez peut-être ajouter d'autres implémentations plus tard, par ex. après l'installation de l'application.
Si c'est le cas, vous devrez probablement utiliser un chargeur de classe personnalisé. Par exemple, vous pouvez autoriser les utilisateurs à placer des fichiers jar dans un dossier particulier et à ajouter les noms de classe des implémentations dans un fichier de propriétés. Vous auriez alors besoin d'un chargeur de classe personnalisé capable de charger des classes à partir des fichiers JAR présents dans ce dossier, et vous utiliseriez ce chargeur de classe pour charger les classes (par exemple en utilisant Class.forName (className, classLoader)).
En fait, si vous avez un chargeur de classes par fichier jar, vous pourrez avoir plusieurs classes avec les mêmes noms dans les fichiers jar, car le chargeur de classe définit les limites des noms de classes. C'est à peu près ce que fait OSGI.
est ici un code relatif aux classes de chargement de pots:
http://sourceforge.net/projects/jcloader/ http://www.javaworld.com/javatips/jw-javatip70.html
Ce n'est pas possible sans jouer avec mesure classloaders (et peut même ne pas être possible alors). Peut-être que si vous expliquiez ce que vous essayez d'accomplir, vous auriez plus d'aide. –
OSGI semble très intéressant cependant, peut-être que j'aborde ce problème incorrectement. Dans un sens moins générique, voici ce que j'essaie d'accomplir. J'ai un shell du jeu Oware qui gère la mécanique du jeu. Il demande aux autres classes de faire leurs mouvements en leur envoyant l'état du jeu et en retournant un coup. Je voudrais avoir un dossier d'IA contenant du code différent, il pourrait y en avoir beaucoup. Le shell lancera ensuite un tournoi à la ronde sur tous les IA qu'il trouve et sortira avec qui les IA gagneront. – JonLeah