Runnable Java Procs in JRuby
One of the cool features of the JRuby Swing GUI builder library, Profligacy (by the ever awesome Zed Shaw of Mongrel fame) is the Proc#to_runnable method that converts procs into a java.lang.Runnable interface that can be passed into any Java method that accepts an instance of Runnable, such as java.lang.Thread.new(). Profligacy's implementation looks something like this:
class RunnableProc
include java.lang.Runnable
def initialize &block
@block = block
end
def run
@block.call
end
end
class Proc
def to_runnable
RunnableProc.new &self
end
end
I prefer doing this instead:
class Proc
include java.lang.Runnable
alias_method :run, :call
end
p=Proc.new do
puts 'running'
end
The only disadvantage to that is that you can't use the familiar proc { ... } and lambda {...}, but I like having a simple 4-liner. And the Runnable interface is really useful in JRuby for working around protected Java methods when creating JRuby subclasses: I can mock up and compile a simple Java subclass that accepts a Runnable, then instantiate it in JRuby with a Proc. For example, the java.util.TimerTask class has a protected constructor, so you can't instantiate it in JRuby, even as a subclass, because a subclass is really a subclass of JavaProxy with an instance variable of the Java class. So:
//RubyTimerTask.java
public class RubyTimerTask extends java.util.TimerTask
{
public Runnable task;
public RubyTimerTask(Runnable r){
this.task = r;
}
public void run(){
this.task.run();
}
}
#timer_test.rb
include_class 'RubyTimerTask'
p = Proc.new { puts 'running' }
rtt = RubyTimerTask.new p
t=java.util.Timer.new
t.schedule rtt, 2000 #run in 2 seconds
t.cancel #join the Timer's thread