Skip to content

Method Signatures and Annotations in JRuby extensions

Martin Prout edited this page Mar 7, 2016 · 26 revisions

Class method signatures

# in ruby

def active?
end
// java, note active_p follows the naming convention for a query

@JRubyMethod(name = "active?")
public IRubyObject active_p(ThreadContext context) {
}
# in ruby we might have vector normalize

def normalize
end
// java, norm we will return a normalized copy leaving original unchanged

@JRubyMethod(name = "normalize")
public IRubyObject norm(ThreadContext context) {
}
# in ruby we might have vector normalize, where we change the original

def normalize!
end
// in java, the normalize_bang follows the naming convention for a hard change
// eg in vector normalize the original is changed

@JRubyMethod(name = "normalize!")
public IRubyObject norm_bang(ThreadContext context) {
}

rest arguments

# ruby

def initialize(*args)
end
// java

@JRubyMethod(name = "initialize", rest = true)
public IRubyObject initialize(ThreadContext context, IRubyObject[] args) {
}

arguments with default value

# ruby

def get(key, marshal=true)
end
// java (the default value for required and optional is 0)

@JRubyMethod(name = "get", required = 1, optional = 1)
public IRubyObject get(ThreadContext context, IRubyObject[] args) {
    Ruby ruby = context.getRuntime();
    RubyString key = (RubyString) args[0];
    RubyBoolean marshal = ruby.getTrue();
    if (args.length > 1) {
        marshal = args[1];
    }
}

initialize or new

# ruby

attr_reader :x, :y

def initialize(*args)
  if args.length == 2
    @x = args[0]
    @y = args[1]
  else
    @x = 0
    @y = 0
  end
end
// java where meta = true mean this method should be defined on the metaclass

/**
 *
 * @param context ThreadContext
 * @param klazz IRubyObject
 * @param args optional (no args jx = 0, jy = 0)
 * @return new Vec2 object (ruby)
 */
@JRubyMethod(name = "new", meta = true, rest = true)
public static final IRubyObject rbNew(ThreadContext context, IRubyObject klazz, IRubyObject[] args) {
    Vec2 vec2 = (Vec2) ((RubyClass) klazz).allocate();
    vec2.init(context, args);
    return vec2;
}

/**
 *
 * @param runtime Ruby
 * @param klass RubyClass
 */
public Vec2(Ruby runtime, RubyClass klass) {
    super(runtime, klass);
}

void init(ThreadContext context, IRubyObject[] args) {
    if (Arity.checkArgumentCount(context.getRuntime(), args, Arity.OPTIONAL.getValue(), 2) == 2) {
        jx = (Double) args[0].toJava(Double.class);
        jy = (Double) args[1].toJava(Double.class);
    }
}

Module method signatures

module Foo 
  def build_string
     return 'This is a new String' 
     end alias_method :build_string :new_string
  end
end

Note in java the module method is a static method, and requires a receiver, also illustrated below is how to create an alias (there is an alias option in jruby annotations but it is not required just name the method as below

/**
*
* @param context ThreadContext
* @param recv the receiver
* @return A RubyString.
*/
@JRubyMethod(name = {"build_string", "new_string"}, module = true)
public static IRubyObject buildString(ThreadContext context, IRubyObject recv) {
    Ruby runtime = context.getRuntime();
    return runtime.newString("This is a new String");
}

Clone this wiki locally