在Jruby中覆盖Java方法的麻烦

时间:2018-07-14 13:21:55

标签: java ruby jruby

我在从jruby类覆盖Java方法时遇到了一些麻烦。由于JRuby公开了同时使用驼峰和蛇格语法的Java方法,因此我尝试了两种方法来覆盖相同的方法,但结果却很奇怪:

JAVA

package tabaqui;

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

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

红宝石

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"

我发现获得预期结果(在每种情况下都调用红宝石方法)的唯一解决方案是在ruby中定义覆盖方法后为其赋予别名:

alias_method :myMethod, :my_method

我做错什么了吗?

1 个答案:

答案 0 :(得分:1)

一见钟情,但一旦您理解了别名,这就是“预期” ...

MyJavaClass#myMethod将由JRuby运行时设置一个my_method别名。

MyRubyClass1中的

中,您重新定义了my_method(别名),从而看到了预期的输出。 但是您没有覆盖myMethod->约定不能向后使用。

MyRubyClass2中,您重新定义了myMethod,因此最终它会从invokeMyMethod()进行虚拟Java调度。

这看起来似乎很混乱,但Java别名约定确实适用于“裸机”使用者。而如果要扩展Java类,则应使用适当的Java名称。生成代理类后,这里有改进的余地来重新定义Java别名,尽管这可能是一个重大更改。