4

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.

3
  • Um... why? How is this going to help? I think it'd obfuscate what your code is doing, and not in a good way. Commented Nov 20, 2013 at 1:01
  • In jruby I commonly find myself pushing ruby code down into java implementations for performance reasons. Commented Nov 20, 2013 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. Commented Nov 20, 2013 at 1:20

1 Answer 1

6
+50

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.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.