Re: Passing a Method Name to a Method
On 6/22/2011 12:46 PM, Gene Wirchenko wrote:
Dear Jav'ers:
Maybe I will find this after searching more, but so far, no good.
I want to pass a parameter of a method name to another method.
As others have said, you can't do this literally. However you have a
few options using interfaces, classes, dependency injection, and good
ol' software engineering.
First, the interface/class method:
public class Parser {
final private Language parser;
public Parser( Language parser ) {
this.parser = parser;
}
public parse( Reader in ) {
parser.parse( in );
}
}
Here, you use a Parser which uses dependency injection to determine
which language you are going to parse. You use it like this:
Parser p = new Parser( new JavaParser() );
p.parse( System.in ); // parse stdin
Where JavaParser is:
public class JavaParser implements Language { ...
and
public interface Language {
parse( Reader in );
}
You could of course pass in the language at the same time, but that's a
little less OOD.
public class Parser {
public static parse( Language parser, Reader in ) {
parser.parse( in );
}
}
Note that the "don't do it in Java" guy, Fuschia, is off his rocker.
This is very efficient in Java as the JVM will recognize the JavaParser
class is effectively final and optimize the call to use non-virtual calls.
You can also do similar things with Runnable or Callable, which just
avoids declaring a type. Since declaring a type isn't that big of a
deal, this is usually poor solution unless you are in fact spawning
threads and using the concurrency API directly.
public class Parser {
final private Runnable parser;
public Parser( Runnable parser ) {
this.parser = parser;
}
public parse() {
parser.run();
}
}
You might call this with an anonymous class rather than declaring a yet
another type, however again that might not really be worth it. I'm
drawing a blank here how to pass in arguments to the run method, so I'll
cheat:
Parser p = new Parser( new Runnable() {
private final Reader in = System.in;
public void run() {
new JavaLanguage.doIt( in );
}
} );
p.parse(); // parse stdin
Note that when you see this for "real", say in the Java API, you'll
typically use a factory method, not instantiate an injectable object.
(For example, both the ScriptEngineManager and
javax.xml.parsers.DocumentBuilder use factory methods.) So don't ignore
the Factory Pattern in your own designs as well.
Parser p = Parser.getParser( "Java" );
p.parse( System.in ); // parse stdin
No code compiled or tested. ;)