views:

389

answers:

6

I've looked all around and I haven't been able to figure out how to accomplish this.

What I'd like to be able to do is to load set of classes, probably all in the same folder. All of which implement the same interface and are the same class, then in my code I'd like to be able to call functions on those classes.

Any help you can give, or even just a push in the right direction would be great. Thanks!

+1  A: 
  1. If you can use OSGI, its as simple as snapping a finger! In oSGI you can have multiple verssions of the same class. All you do is have same bundles with different versions.

  2. Otherwise you can still write your custom class loader that reads both the classes. One way of doing it would be like this. You write two ClassLoaders, one of them loads one version of the class and the other loads the other version of the class. Now based on the need you choose the classloader1 or classloader2 to load the class. So now you can also have multiple versions of the same class loaded simultaneously in the memory.

Note: Make sure this is actually you want to do, there may be other ways of coming around your problem.

Suraj Chandran
i can has osgi?
Jason S
@jason...i did not get you :)
Suraj Chandran
"as simple as snapping a finger"... That is a bold statement in regards to OSGi.
Thilo
@thilo...ya, i guess so, maybe i have got too used to osgi...seems like my subconcious is playing games here:)
Suraj Chandran
+1  A: 

The only framework I know which does support what you are after is OSGI:

alt text

Its network model, described in this article "Exposing the boot classpath in OSGi", does allow that

One of the side effects (or aims) of the networking model is type isolation or class versioning: multiple version of the same class can coexist nicely inside the same VM since each one is loaded into its own network, its own space.

See this tutorial for beginning and choose on eof the OSGI Framework (like Equinox, Knoplerfish or Apache Felix)

VonC
+4  A: 

Based on your answer to my question, it seems you want to define a game interface and then plug in any number of AI implementations, probably configured from a .properties file. This is fairly standard use of an API interface.

You define an EngineInterface providing a method that accepts game state and returns the move. Then you define multiple classes that all implement EngineInterface. Your driver reads a property file to get the names of the implementation classes, instantiates them with Class.forName() and stores them in a list and/or map. Then when the driver gets requests it invokes each implementation in turn and keeps track of the results.

Jim Garrison
+2  A: 

Have you tried something like:

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;

Each class would implement its own algorithm for generating a move, but would be called but called by common method

Dave L Delaney
+2  A: 

Hello,

It is possible to do what you want with OSGI but you could as well use a custom classloader. The idea is that you have to instanciate a classloader for every version of the class you want to load. Here you can find a good explanation.

But I think what you really need to solve your problem is something based on interfaces like described by Jim Garrison or Dave L Delaney...

pgras
A: 

It can be done using dynamic class loading. It is not loading class of different version but different sub-classes of a super class or interface.

The important steps are:

(1) Use Class.forName(...) to load a class by name. The class must be in the class path.

(2) Use aClass.newInstance() to instantiate the object. This is easy if there is no parameter needed for the constructor.

The following code should provide some idea for you. It does not handle exception which you have to do it.

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) {
        // ...
    }
}

Hope this helps.

NawaMan