2

I am learning how to integrate Java library with Ruby code and come to the following question.

I have a command pattern implemented in Java, as follows:

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]";
  }
}

When I import that to JRuby program I can implement Ruby class that respond_to? :execute with one parameter and pass it to the CommandRunner.new.run. That works and that's clear.

But I can also do this:

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

Instead of passing to Java CommandRunner an object implementing the execute method I pass it a block of code, that does not implement the method. And It works: calls the block as if it was implementation of the execute method! How is that possible? What does JRuby do with the block when passing it to Java? If I had the CommandRunner implemented in Ruby the above code would not work.

wrzasa
  • 1,113
  • 10
  • 20
  • i suspect that something adds an `execute` method to your proc object. you could check that in your `put_through_runner` method. – phoet Nov 05 '13 at 15:05
  • Nothing adds the `execute` method. First: there is nothing that could do it, second: that was the first thing I checked -- in the `put_through_runner` method the `block` object does not `respond_to? :execute`. – wrzasa Nov 06 '13 at 21:43
  • having `respond_to?` returning `false` does not necessary mean that this is actually the case. it depends on the way `respond_to?` is implemented. – phoet Nov 06 '13 at 21:45

1 Answers1

3

The reason that this works is a feature called 'closure conversion' (see docs here). What happens is that the block you pass is converted into a Proc object with a proxy that invokes the code in the block for any method that is called on the object.

Paul Morie
  • 15,528
  • 9
  • 52
  • 57
  • Great answer! I'm very grateful. I had not idea where to look for an explanation and how can I exploit this feature. Now that's clear. BTW: very nice feature of JRuby – wrzasa Nov 06 '13 at 21:46