I have prepared a simple base class that takes a few arguments in the constructor, like this:
public class TargetDescription {
private String description;
private String category;
public TargetDescription(String description, String category) {
this.description = description;
this.category = category;
}
public void apply() {
}
}
I have then tried to subclass this as follows:
TargetDescription a = new TargetDescription("a", "b") {
public void apply() {
System.err.println("Hello");
}
};
but when I do I get error message like the following:
Target exception: Sourced file: testt.bsh : Typed variable declaration : Error constructing inner class instance: bsh.ReflectError: Can't find constructor: global$1( java.lang.String, java.lang.String ) in class: global$1 : at Line: 1 : in file: testt.bsh : new TargetDescription ( "a" , "b" ) {
Logged In: YES
user_id=812261
Originator: NO
It looks like this is a dupe of bug #1627493.
The problem is that the generated code does not know how to call the superclass constructor. The default is to insert a default no-args constructor, which is why this works in some situations and not others.
I have made a hack/patch that fixes this behavior. It basically inserts a method that looks like a constructor and calls super with the argument types specified in the allocator. This is as localized and non-intrusive as I could think to make it. It seems to work.
Patch is as follows.
<pre>
*** Copy of BeanShell-2.0b5\src\bsh\BSHAllocationExpression.java Sat Jun 11 23:16:42 2005
--- BeanShell-2.0b5\src\bsh\BSHAllocationExpression.java Tue Sep 25 12:50:16 2007
***************
*** 34,39 ****
--- 34,40 ----
package bsh;
+ import java.io.StringReader;
import java.lang.reflect.Array;
import java.lang.reflect.InvocationTargetException;
***************
*** 179,188 ****
{
//throw new InterpreterError("constructWithClassBody unimplemented");
! String name = callstack.top().getName() + "$" + (++innerClassCount);
Modifiers modifiers = new Modifiers();
modifiers.addModifier( Modifiers.CLASS, "public" );
Class clas;
try {
clas = ClassGenerator.getClassGenerator() .generateClass(
name, modifiers, null/*interfaces*/, type/*superClass*/,
--- 180,212 ----
{
//throw new InterpreterError("constructWithClassBody unimplemented");
! String inner = "anon" + (++innerClassCount);
! String name = callstack.top().getName() + "$" + inner;
Modifiers modifiers = new Modifiers();
modifiers.addModifier( Modifiers.CLASS, "public" );
Class clas;
+
+ // If the class was created with arguments then add a constructor that simple invokes super
+ if (args.length > 0) {
+ String formal = "";
+ String argnames = "";
+ for (int i=0; i<args.length; i++) {
+ if (i>0) {
+ formal += ", ";
+ argnames += ", ";
+ }
+ String argname = String.valueOf((char) (97+i));
+ argnames += argname;
+ formal += args[i].getClass().getName()+" "+argname;
+ }
+ String command = inner+"("+formal+") {super("+argnames+");}";
+ Parser p = new Parser(new StringReader(command));
+ p.Line();
+ BSHMethodDeclaration node = (BSHMethodDeclaration) p.popNode();
+ node.eval(new CallStack(), new Interpreter());
+ block.jjtAddChild(node, block.jjtGetNumChildren());
+ }
+
try {
clas = ClassGenerator.getClassGenerator() .generateClass(
name, modifiers, null/*interfaces*/, type/*superClass*/,
</pre>
Ticket has been migrated to github.
Please follow up on this over here: https://github.com/beanshell/beanshell/issues/418