2016-05-11 4 views
0

Потенциально немой вопрос, но я не мог найти прямой документации об этом, так что вот оно.выставить метод toString для объектов js в nashorn

Я хотел бы предоставить Java-конструктор стороне JS, при создании экземпляра он должен создать экземпляр с методом «toString».

// java class 
import javax.script.ScriptEngine; 
import javax.script.ScriptEngineManager; 
import jdk.nashorn.api.scripting.AbstractJSObject; 

public class Foo extends AbstractJSObject { 
    String bar; 

    public Foo() { 
     super(); 
    } 

    public Foo(String b) { 
     super(); 
     this.bar = b; 
    } 

    @Override 
    public Object newObject(Object... args) { 
     String bar = null; 
     if (args[0] != null) bar = args[0].toString(); 

     Foo f = new Foo(bar); 
     return f; 
    } 

    @Override 
    public String toString() { 
     return "Foo: " + this.bar; 
    } 


    public static void main(String[] args) { 
     ScriptEngine engine = new ScriptEngineManager().getEngineByName("nashorn"); 
     engine.put("foo", new Foo()); 

     // f.toString however is null 
     engine.eval("var f = new foo('hi'); f.toString();") 
    } 
} 
+0

ли код, который вы в настоящее время не сделать это? В чем проблема, с которой вы столкнулись в данный момент? –

+0

@ PeterDavidCarter-Poulsen Это не так. toString имеет значение null для экземпляров из нового foo (...) –

ответ

1

Если вы реализуете JSObject, Насхорн маршрут будет все доступы недвижимость/индекс, вызовы с помощью методов JSObject как getMember, getSlot, setMember, setSlot, методы вызова , Я немного изменил свой код, чтобы выставить «ToString» как свойство вашего объекта Foo и сделал это компилируемый & работоспособного кода:

import javax.script.ScriptEngine; 
import javax.script.ScriptEngineManager; 
import jdk.nashorn.api.scripting.AbstractJSObject; 
import java.util.function.Supplier; 

public class Foo extends AbstractJSObject { 
    String bar; 

    public Foo() { 
     super(); 
    } 

    public Foo(String b) { 
     super(); 
     this.bar = b; 
    } 

    @Override 
    public Object newObject(Object... args) { 
     String bar = null; 
     if (args[0] != null) bar = args[0].toString(); 

     Foo f = new Foo(bar); 
     return f; 
    } 

    @Override 
    public Object getMember(String name) { 
     if (name.equals("toString")) { 
      // Returning a lambda function as value of this property. 
      // nashorn code can call lambdas just like script functions! 
      // You may also choose to return another JSObject that 
      // returns true in isFunction() method and implements "call" 
      // as well. 

      return (Supplier<String>)this::toString; 
     } else { 
      // implement other exposed properties here. 
      return null; 
     } 
    } 

    @Override 
    public String toString() { 
     return "Foo: " + this.bar; 
    } 


    public static void main(String[] args) throws Exception { 
     ScriptEngine engine = new ScriptEngineManager().getEngineByName("nashorn"); 
     engine.put("foo", new Foo()); 

     // f.toString() would call getMember("toString") and the 
     // returning lambda is called! 

     engine.eval("var f = new foo('hi'); print(f.toString());"); 
    } 
} 
+0

Спасибо! Теперь имеет смысл сказать, что вы упомянули об этом. Желание документа было более ясным в объяснении этого. –

0

Вы можете попробовать таким образом:

import javax.script.*; 

    import jdk.nashorn.api.scripting.AbstractJSObject; 

    public class Foo extends AbstractJSObject { 
     String bar; 

     public Foo() { 
      super(); 
     } 

     public Foo(String b) { 
      super(); 
      this.bar = b; 
     } 

     @Override 
     public Object newObject(Object... args) { 
      String bar = null; 
      if (args[0] != null) bar = args[0].toString(); 

      Foo f = new Foo(bar); 
      return f; 
     } 

     @Override 
     public String toString() { 
      return "Foo: " + this.bar; 
     } 


     public static void main(String[] args) throws ScriptException { 
      ScriptEngine engine = new ScriptEngineManager().getEngineByName("javascript"); 
      engine.put("foo", new Foo()); 

      Compilable compilable = (Compilable) engine; 
      Bindings bindings = engine.createBindings(); 
      String script = "function add(op1,op2){return op1+op2} add(a, b)"; 
      CompiledScript jsFunction = compilable.compile(script); 
      bindings.put("a", 1);bindings.put("b", 2); //put java object into js runtime environment 
      Object result = jsFunction.eval(bindings); 
      System.out.println(result); 
     } 
    } 
+0

Как это решить проблему, что toString не является методом на "new foo ('bar')"? –