Search code examples
javarubyjruby

Troubles overriding java method in jruby


I'm having some troubles overriding a java method from a jruby class. Since JRuby exposes java methods with both camel and snake case syntaxes, i've tried both approaches to override the same method, but i'm having strange results:

JAVA

package tabaqui;

class MyJavaClass {
  public void myMethod() {
    System.out.println("Java method");
  }

  public void invokeMyMethod() {
    myMethod();
  }
}

RUBY

class MyRubyClass1 < Java::tabaqui.MyJavaClass
  def my_method
    puts "Ruby method from MyRubyClass1\n";
  end
end

class MyRubyClass2 < Java::tabaqui.MyJavaClass
  def myMethod
    puts "Ruby method from MyRubyClass2\n";
  end
end

a = MyRubyClass1.new
a.my_method          #output: "Ruby method from MyRubyClass1"
a.invoke_my_method   #output: "Java method"

b = MyRubyClass2.new
b.my_method          #output: "Java method"
b.invoke_my_method   #output: "Ruby method from MyRubyClass2"

The only solution i've found to obtain the expected result (ruby methods invoked in every case) is giving the overridden method an alias after defining it in ruby:

alias_method :myMethod, :my_method

Am i doing something wrong?


Solution

  • while confusing at first sight, this is "expected" once you understand alias ...

    MyJavaClass#myMethod will have a my_method alias setup by the JRuby runtime.

    in MyRubyClass1 you redefined my_method (alias) thus seeing the expected output. however you did not override myMethod -> the convention does not work backwards.

    while in MyRubyClass2 you redefined myMethod so it ends up doing virtual Java dispatch from invokeMyMethod(), es expected.

    while this might seem confusing its how it is, the Java alias conventions are really there for "bare" consumers. while if you're extending a Java class you should stick to proper Java names. there's room for improvement here to re-define Java aliases once a proxy class is generated, although it might be a breaking change.