Hey all. Is it possible, in a JRuby app, to override a method in a Java class? For example, given a Java class com.foo.Bar that has some method m, I want to change the behavior of m. I know I can do this in a subclass, but I want to alter the behavior of the Java class itself. Thanks, James Britt -- Neurogami - Avant-garage Research & Development http://www.neurogami.com james@neurogami.com
on 2013-01-26 19:26
on 2013-01-26 20:00
Yes, I did this:
com.myco.MyClass.class_eval do
alias :real_myMethod :myMethod
def myMethod *args
# do stuff
real_myMethod *args
# do other stuff
end
end
and it seemed to work. jruby 1.7.0 jdk7u11
-Dave
aside:
I used this approach to display the ruby call stack when a java
exception was thrown inside the method. The code I wrote looks like:
def myMethod *args
begin
real_myMethod *args
rescue Exception
puts 'exception caught in method execution - dumping ruby call
stack'
caller.each do |st|
puts st
end
raise
end
end
Please let me know if you have any comments or suggestions for
improvement
on 2013-01-26 20:10
This might not work, as real_myMethod will not only invoke by Ruby code, it also can be invoked inside Java code too. Lei Gao From: Dave Liebreich <dave.liebreich@gmail.com> To: user@jruby.codehaus.org Sent: Saturday, January 26, 2013 10:59 AM Subject: Re: [jruby-user] Is it possible to override a method in a Java class Yes, I did this: com.myco.MyClass.class_eval do alias :real_myMethod :myMethod def myMethod *args # do stuff real_myMethod *args # do other stuff end end and it seemed to work. jruby 1.7.0 jdk7u11 -Dave aside: I used this approach to display the ruby call stack when a java exception was thrown inside the method. The code I wrote looks like: def myMethod *args begin real_myMethod *args rescue Exception puts 'exception caught in method execution - dumping ruby call stack' caller.each do |st| puts st end raise end end Please let me know if you have any comments or suggestions for improvement On Saturday, January 26, 2013 at 10:24 AM, James Britt wrote: Hey all.
on 2013-01-26 23:37
Dave - I'm surprised that the modifications you made worked. I suspect that JRuby added a wrapper class around the Java class, and modified that wrapper. I'm pretty sure that class modifications of a Java class in Ruby code would be seen only on the Ruby side. Given that it did work, though, I suspect that the Java class accessed in Java code would ignore the modifications. It should be pretty easy to put together a test, but I don't have time at the moment. - Keith --- Keith R. Bennett http://about.me/keithrbennett
on 2013-01-26 23:38
Dave - I'm surprised that the modifications you made worked. I suspect that JRuby added a wrapper class around the Java class, and modified that wrapper. I'm pretty sure that class modifications of a Java class in Ruby code would be seen only on the Ruby side. Given that it did work, though, I suspect that the Java class accessed in Java code would ignore the modifications. It should be pretty easy to put together a test, but I don't have time at the moment. - Keith --- Keith R. Bennett http://about.me/keithrbennett
on 2013-01-27 00:24
Yes, I did not need the modifications to work when the original java method was called from java code. I only needed them to be in place when the method was called from jruby code. Since the original request mentioned "in a JRuby app", I thought my approach might help. -Dave
on 2013-01-27 00:51
Dave - On Jan 26, 2013, at 6:23 PM, Dave Liebreich <dave.liebreich@gmail.com> wrote: > Yes, I did not need the modifications to work when the original java method was called from java code. I only needed them to be in place when the method was called from jruby code. Oh, I see. > Since the original request mentioned "in a JRuby app", I thought my approach might help. Yes, hopefully it would. However, "a JRuby app" can make heavy use of Java libraries that use callbacks. For example, my "Game of Life Viewer" (article: http://www.bbs-software.com/blog/2012/09/05/conway..., code: https://github.com/keithrbennett/life_game_viewer) is a JRuby app that uses Java Swing for the GUI framework. Swing makes heavy use of callbacks. So that's an example of a JRuby app in which the directly-modify-Java-class approach would not work (I don't think), whereas the subclass-Java-class approach would. Pretty cool what you did though. Thanks, Keith
on 2013-01-27 00:52
Dave - On Jan 26, 2013, at 6:23 PM, Dave Liebreich <dave.liebreich@gmail.com> wrote: > Yes, I did not need the modifications to work when the original java method was called from java code. I only needed them to be in place when the method was called from jruby code. Oh, I see. > Since the original request mentioned "in a JRuby app", I thought my approach might help. Yes, hopefully it would. However, "a JRuby app" can make heavy use of Java libraries that use callbacks. For example, my "Game of Life Viewer" (article: http://www.bbs-software.com/blog/2012/09/05/conway..., code: https://github.com/keithrbennett/life_game_viewer) is a JRuby app that uses Java Swing for the GUI framework. Swing makes heavy use of callbacks. So that's an example of a JRuby app in which the directly-modify-Java-class approach would not work (I don't think), whereas the subclass-Java-class approach would. Pretty cool what you did though. Thanks, Keith
on 2013-01-27 06:46
Keith Bennett wrote: > that uses Java Swing for the GUI framework. Swing makes heavy use of > callbacks. > > So that's an example of a JRuby app in which the > directly-modify-Java-class approach would not work (I don't think), > whereas the subclass-Java-class approach would. Pretty cool what you did > though. Thanks very much for these answers. I spent more time looking into this, adding yet more proof that the surest way to solve a problem is to post a question about it because inevitable (well, maybe) one then figures it out. Turns out that i was not able to get my code to work at first because I was not correctly addressing the class of interest. Instead I was creating a new class; the intended target of this code was unaware. Once I was able to refer to the correct class I did this: class Java::ComLeapmotionLeap::Frame alias_method :leap_hands, :hands def hands hands = leap_hands # My own nefarious code here # ... end end In actual use a Frame object (created by third-party Java code) is passed to a callback method (onFrame) that has to be defined in a Listener class that handles the callback. In my JRuby app that class is sub-classed from a Java class. The objects (and sub-objects) it gets passed though can be already modified with whatever enhancements I see fit. Which, of course, is very cool. Thanks again! James
Please log in before posting. Registration is free and takes only a minute.
Existing account
(Switch to SSL-encrypted connection)
NEW: Do you have a Google/GoogleMail or Yahoo account? No registration required!
Log in with Google account | Log in with Yahoo account
Log in with Google account | Log in with Yahoo account
No account? Register here.