Currently, in order to implement a Java interface in JRuby, you extend from it like so:
require 'java'
include_class "java.awt.event.ActionListener"
class MyActionListener < ActionListener
def actionPerformed(event)
puts event
end
end
While documenting a JRUBY-66 workaround and thinking about a longterm fix, it hit me like a diamond bullet through my forehead: interfaces should be treated like modules.
My justification:
- You can include many modules, but only extend one class...just like interfaces. Currently in JRuby you can only implement one interface, which is stupid.
- Modules imply a particular set of behaviors not specific to a given class hierarchy...just like interfaces.
- Ruby implementations of Java interfaces can't extend any other classes; you can't both extend Array and implement Collection, if that were your goal.
- Ruby implementations of Java interfaces have bugs when defining initialize, since they don't really just implement that interface...they extend one of our JavaSupport proxies.
Item #3 limits your ability to re-open core Ruby classes and add new Java interfaces to them, something that might greatly simplify mapping Ruby types to Java-land.
Item #4 is the cause of JRUBY-66, since we need to make sure the proxy's initializer is called.
In our defence, we inherited much of this Java integration behavior from the original project owners; however I think mapping interfaces to modules allows for much more powerful and uniform Java integration support.
I know it would be a fairly significant change to make Java interfaces
act like modules, but it seems much more logical to me. It's also primarily a new feature we could phase in, with the < syntax continuing to work for old style interface implementation.
Thoughts?
# yes, I know encapsulation would be better...this is just an example
...
include_class "javax.swing.JButton"
class MyActionRecorder < Array
include ActionListener
def actionPerformed(event)
self << event
end
end