Tom recently filed an issue for a feature we've wanted: to have the
modules associated with Java interfaces also contain the methods from
those interfaces.

Currently, if you list the methods on an interface module, you won't
see any of the Java interfaces methods. This makes it difficult to use
meta-programming on those interfaces, either by adding default stubs
or by inspecting the methods a given interface has.

So I started by making the naive change to just go ahead and bind the
methods, but I ran into a chicken/egg problem (probably the same
problem I ran into when I tried this years ago).

Say we have this interface:

public interface DoIt {
  public void doIt();
}

We can implement this in Ruby using either "doIt" or "do_it", the
latter by popular demand some years ago.

If we use "do_it", we run into a problem with my changes.

The current interface implementation logic basically just defines in
the new class a "doIt" Java method that redispatches to "doIt" and
"do_it" in Ruby in turn. That way, if you don't define a Ruby "doIt"
but you do define "do_it", the Java "doIt" will eventually call your
"do_it" Ruby code.

If, as in my current patch, the interface modules actually bind the
methods associated with them, the behind-the-scenes redispatch inside
the interface-impl "doIt" *does* find a Ruby "doIt" method...the stub
we bound into the module. So you have this:

Pre-patch:

* Java calls "doIt"
* Interface impl of "doIt" searches the Ruby class for "doIt" and
"do_it" in turn
* Eventually it finds "do_it" because there's no "doIt" defined in Ruby
* "do_it" is called in Ruby

Post-patch:

* Java calls "doIt"
* Interface impl of "doIt" searches the Ruby class for "doIt" and
"do_it" in turn
* It finds the Ruby "doIt" we bound into the interface module
* The bound "doIt" assumes we're calling a Java class, and
reflectively dispatches to the Java "doIt"
* Lather, rinse, and repeat"

It blows the stack, because the Java version of "doIt" wants to call
the Ruby version of "doIt", and the Ruby version of "doIt" wants to
call the Java version.

I'm pondering how to get around this. There's a few options that aren't great:

* Make the interface module version of the method do the same search
for all names, but have it explicitly ignore module methods. This
would break including a Ruby module to provide the bodies of Java
interface methods (and might be tricky anyway).
* When implementing a Java interface method using a different name,
always also reimplement the real name. This might be hard to figure
out, since the odd names will look like normal Ruby methods.
* Have the generated interface impl look for the real name *last*,
allowing Ruby names to take priority. This might work, but it would
change lookup order (but they're cached, so it wouldn't impact perf).

I'm going to try the third option, but I'm open to other suggestions.

- Charlie

---------------------------------------------------------------------
To unsubscribe from this list, please visit:

    http://xircles.codehaus.org/manage_email


Reply via email to