Tell me more ×
Stack Overflow is a question and answer site for professional and enthusiast programmers. It's 100% free, no registration required.

In Ruby, I can have a module like:

module Greeter
  def greet
    print "Hello"
  end
end

And my class can get the greet method like this:

class MyClass
  include Greeter
end

obj = MyClass.new
obj.greet

Now, I would like to have my module Greeter implemented in Java instead. I'm using JRuby. I'm unsure about how to create a Ruby module in Java (in such a way that I can do include normally).

For a moment I though of making a Java interface. Including it in my Ruby class doesn't throw errors, but it really isn't the same thing since modules seem to implement the methods, whereas a Java interface doesn't.

share|improve this question
 
Um... why? How is this going to help? I think it'd obfuscate what your code is doing, and not in a good way. –  the Tin Man Nov 20 at 1:01
 
In jruby I commonly find myself pushing ruby code down into java implementations for performance reasons. –  phs Nov 20 at 1:02
 
@theTinMan: Mostly curiosity. Frankly though, hiding such module wouldn't be so bad for me. I'm writing a game development framework and honestly, the end-user definitely doesn't want to mess around with this module - they only need (and should) include it in their Ruby classes. –  Omega Nov 20 at 1:20

This question has an open bounty worth +50 reputation from Omega ending in 6 days.

This question has not received enough attention.

1 Answer

Here's how would implement exactly the same code you have above using a Java extension.

Everything here is at the default package level (no package), if you would like to have packages just change the module name.

First, create the Greeter class:

import org.jruby.anno.JRubyMethod;
import org.jruby.runtime.ThreadContext;
import org.jruby.runtime.builtin.IRubyObject;

public class Greeter {

    @JRubyMethod
    public static void greet( ThreadContext context, IRubyObject self ) {
        System.out.printf("Hello from %s%n", self);
    }

}

Then you need the GreeterService to load it:

import org.jruby.Ruby;
import org.jruby.RubyModule;
import org.jruby.runtime.load.BasicLibraryService;

import java.io.IOException;

public class GreeterService implements BasicLibraryService {

    @Override
    public boolean basicLoad(final Ruby runtime) throws IOException {
        RubyModule greeter = runtime.defineModule(Greeter.class.getSimpleName());
        greeter.defineAnnotatedMethods(Greeter.class);

        return true;
    }

}

And with these classes defined, here's how you can use them in a JRuby script:

require 'target/jruby-example.jar'
require 'greeter'

class MyClass
  include Greeter
end

obj = MyClass.new
obj.greet

The jruby-example.jar contains both classes above compiled and packaged. There isn't much else to be done here, now you have your module that you can include anywhere. For a bigger example, just check how the Enumerable module is implemented.

share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.