Menu

#280 Cannot anonymous subclass with arguments

None
closed
nobody
Parsing (77)
5
2018-08-02
2007-01-09
Anonymous
No

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" ) {

Discussion

  • Opeongo

    Opeongo - 2007-09-25

    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>

     
  • nickl-

    nickl- - 2018-08-02
    • status: open --> closed
    • Group: -->
     
  • nickl-

    nickl- - 2018-08-02

    Ticket has been migrated to github.
    Please follow up on this over here: https://github.com/beanshell/beanshell/issues/418

     

Log in to post a comment.