3

Have a Java class with an overloaded method:

public void test(float x) {

}

public void test(RubyArray array) {

}

In Ruby,

object.test(1.0)

Works fine. However:

object.test([1.0,2.0])

Will crash with the message:

org.jruby.exceptions.RaiseException: (NameError) no method 'test' for arguments (org.jruby.RubyArray) on Java::MyNamespace::MyClass
  available overloads:
    (org.jruby.RubyArray)
    (int)

But, as you can see, that doesn't make any sense. It is telling me that there is no method for my argument of type RubyArray, and then it promptly tells me that there is an available overload for arguments of type RubyArray.

Interestingly, this works fine if you remove the (int) overload, that is, it works if the method that accepts RubyArray has no other overloads.

I have created many overloaded Java methods and used them in Ruby before, so I am guessing that the problem is related mainly to the RubyArray argument itself - although I don't see the issue.

Why is that? What am I doing wrong here?


I am using JRuby 1.7.11, building for what I think is Java SE 6 on Eclipse Kepler for Mac.


To make it easier to test, you can run the following two programs:

This works:

import javax.script.*;

import org.jruby.RubyArray;

public class Main {
    public static void main(String[] args) throws ScriptException, NoSuchMethodException {
        Main app = new Main();
    }
    public Main() throws ScriptException, NoSuchMethodException {
        ScriptEngine jruby = new ScriptEngineManager().getEngineByName("jruby");
        jruby.eval("include Java;\n" + "def start(main) main.test([1,2,3]); end");
        Invocable invocable = (Invocable)jruby;
        invocable.invokeFunction("start",this);
    }
    public void test(RubyArray array) {
        System.out.println(array);
    }
}

This doesn't work:

import javax.script.*;

import org.jruby.RubyArray;

public class Main {
    public static void main(String[] args) throws ScriptException, NoSuchMethodException {
        Main app = new Main();
    }
    public Main() throws ScriptException, NoSuchMethodException {
        ScriptEngine jruby = new ScriptEngineManager().getEngineByName("jruby");
        jruby.eval("include Java;\n" + "def start(main) main.test([1,2,3]); end");
        Invocable invocable = (Invocable)jruby;
        invocable.invokeFunction("start",this);
    }
    public void test(int x) {
        System.out.println(x);
    }
    public void test(RubyArray array) {
        System.out.println(array);
    }
}
Saturn
  • 17,888
  • 49
  • 145
  • 271
  • @kares: Yeah, the problem must be RubyArray. But I wonder why. – Saturn Apr 17 '14 at 10:20
  • my previous edit has not been included thus a new comment: this would work with a `java.util.List` parameter ... I personally do thing it's a flaw in the resolution logic and would report this one (as a feature request) on https://github.com/jruby/jruby/issues ... if you wonder why you'll need to dig into the Java support part of the sources – kares Apr 17 '14 at 12:26

2 Answers2

1

I think this is because in Ruby you can't overload a method with the same number of arguments because there is no data type declaration. You can only overload methods with different numbers of arguments: public void test(int x) vs public void test(RubyArray arr, int x)

So when you call the test-method it flips out and it just takes the first method (don't know how or why it searches or finds the one with the int-param).

Also see this answer: Why doesn't ruby support method overloading?

Community
  • 1
  • 1
B.T.
  • 132
  • 2
  • 15
1

You can specify the type by using java_send (method name symbol), (array of types), *args, e.g.:

object.java_send :test, [RubyArray], [1.0,2.0]

For multiple args not sending an array, btw, it would look like this example from CallingJavaFromJRuby:

list.java_send :add, [Java::int, java.lang.Object], 0, 'foo'
Gary S. Weaver
  • 7,966
  • 4
  • 37
  • 61