在 jruby 中重写 java 方法时遇到问题

Troubles overriding java method in jruby

我在重写 jruby class 中的 java 方法时遇到了一些问题。由于 JRuby 公开了 java 具有骆驼和蛇形大小写语法的方法,我尝试了两种方法来覆盖相同的方法,但我得到了奇怪的结果:

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"

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

alias_method :myMethod, :my_method

我是不是做错了什么?

虽然乍一看令人困惑,但一旦您理解了别名,这就是 "expected"...

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

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

而在 MyRubyClass2 中你重新定义了 myMethod 所以它最终从 invokeMyMethod() 执行虚拟 Java 调度,这是预期的。

虽然这看起来令人困惑,但 Java 别名约定确实适用于 "bare" 消费者。而如果您要扩展 Java class,则应坚持使用正确的 Java 名称。在生成代理 class 后重新定义 Java 别名还有改进的余地,尽管这可能是一个重大变化。