Assuming I understand this approach, would I be correct in saying that
only one plugin could be accessed at a time?
You can load any number of them into a data structure by storing Ballot
references in it.
This would seem to be the way to go as it would appear to allow me to
load multiple 'Ballot' classes at the same time so I could pass the same
set of ballots to the FindWinner method and see the different winners
chosen by each method.
I would likely implement in such a way that each of these plugins uses a
standard naming convention so I can use the Java file directory access
functions to dynamically build the list of plugins to load.
JDK 1.4 and above have classes for storing configuration settings in text
files..you could use those.
However, I am still uncertain about some details on how to make this
work. If anyone knows of a tutorial or some basic sample code showing
how to accomplish this, it would likely answer my questions.
So, let's say that my Ballot class looks something like this:
I have modified your code to reflect things a bit better:
Ballot is an interface, not a class. It's like a C++ pure virtual class.
Basically, if you're familiar with C++, this is the Java way of doing what
you would have done with virtual methods in C++.
public interface Ballot
{
public Ballot() { /* initialization code */ }
public Winner FindWinner( VoterPreference[] ) { /* compute winner */ }
public PrintResults() { /* print results */ }
}
In Java, you implement an interface, and extend a class
public class IRV implements Ballot
{
/* OT editorial comment...IRV...thppt */
public IRV() { /* initialization code */ }
public Winner FindWinner( VoterPreference[] ) { /* compute winner */ }
public PrintResults() { /* print results */ }
}
public class CondorcetRP implements Ballot
{
/* OT editorial comment...CondorcetRP...woo hoo */
public CondorcetRP() { /* initialization code */ }
public Winner FindWinner( VoterPreference[] ) { /* compute winner */ }
public PrintResults() { /* print results */ }
}
Apart from the syntactical glitches, yes, you've got the hang of it, this is
exactly what i had in mind.
1. Are these stored in .java (i.e. as source) or
.jar (i.e. compiled) files?
You would write a separate source file for each class (henceforth i refer to
all plugins as classes, cos thats what they are)
A jar file is something different-it is a compressed file(in ZIP format
actually) containing classes used to distribute applications that are
composed of multiple classes.
You can simply create a zip file and change the extension to jar.
2. Do I need to define a main for each plugin?
If so, what would the main look like?
You need a main only if you plan to run each class on its own. There is
nothing unique about the main method-its like it would be in any other java
program -
public static void main(String args[])
{
}
3. In C++, I can force, for example, CondorcetRP to define
the FindWinner and PrintResults methods. Is this possible
with Java?
The moment class A implements interface B, it HAS to define implementations
for all the methods defined in the interface, or it won't compile.
So it's downright compulsory, not just possible!
In, my application, I could then have something like:
public void runElection(Ballot someballot)
{
/* would write this using an array, but don't know that syntax yet */
Class ballotMethodOne = Class.forName( "CondorcetRP" );
Class ballotMethodTwo = Class.forName( "IRV" );
Yes, this is exactly the syntax!
// ....
}
4. How can I access the FindWinner method which is somewhere in
ballotMethodOne?
The documentation I've found is a bit unclear on this point. It would
appear that I can do something like
Method findWinnerMethod;
findWinnerMethod = ballotMethodOne.getMethod( "Findwinner", /*???*/ );
This is called introspection-and is needed only if you dont know what
methods a class contains. However, in this case you do, cos u have already
defined these methods in Ballot, and all these classes implement Ballot.
In C++ terminology,
when u have a pointer to a base class that has virtual methods-you can call
the virtual method like base->method() without worrying about which child
class is pointed to by the base class pointer.
Same way-in Java-when u have a reference to an interface
(reference
ointer::java:c++) , in this case Ballot, you can call the
methods defined in Ballot without worrying abt the implementing class that
the reference actually refers to.
5. How do I construct the second method that getMethod needs?
The documentation I have is also a bit unclear on how to invoke the
method once I have it. Part of the answer would appear to be:
Winner theWinner;
theWinner = findWinnerMethod.invoke( /*???*/, /*???*/ );
6. Is the first parameter to invoke always the first parameter to the
method I am invoking?
7. Is the second parameter to invoke always an array of parameters to
be passed to the method I am invoking, assuming the method I am
invoking is expecting more then a single parameter to be passed to
it?
I've lost you at this point. Seems like u want to invoke methods on a
totally unknown class that you have instantiated. As i said before-if it
subclasses or implements any of your existing classes/interfaces, you
already know which methods to invoke. If it defines methods of its own,
which are not inherited, then you need to use introspection (there is a
package, i think its called java.lang.introspection) to do this. I tried it
out long ago-its easy. You can easily construct method signatures, find out
their parameters and types etc.