我正在学习如何将Java库与Ruby代码集成,并提出了以下问题。
我有一个用 Java 实现的命令模式,如下所示:
public interface Command {
public String execute(String param);
}
public class CommandRunner {
public String run(Command cmd, String param) {
return cmd.execute(param)+" [this is added by run method]";
}
}
当我将其导入JRuby程序时,我可以实现respond_to? :execute
一个参数的Ruby类并将其传递给CommandRunner.new.run
。这行得通,这很清楚。
但我也可以这样做:
def put_through_runner(param, &block)
CommandRunner.new.run block, param
end
p = put_through_runner "through method" do |param|
"Cmd implementation in block, param: #{param}"
end
puts p
我不是CommandRunner
实现execute
方法的对象传递给Java,而是传递给它一个代码块,它不实现该方法。它有效:调用块,就好像它是execute
方法的实现一样!这怎么可能?JRuby在将块传递给Java时如何处理它?如果我在 Ruby 中实现了CommandRunner
,上面的代码将不起作用。
这起作用的原因是称为"闭包转换"的功能(请参阅此处的文档)。 发生的情况是,您传递的块被转换为具有代理的 Proc
对象,该代理为在对象上调用的任何方法调用块中的代码。