Is it possible to redefine Java classes in JRuby?
How do I redefine existing Java methods in JRuby? Right now it is possible to redefine Ruby methods. I'm asking this because when you write something like
include Java
puts java.io.File.separator
and examine java, io, and File, it turns out that java and io are of type "ruby module" and File is a "class". So I was wondering if it's possible to write something like this and expect it to work
module Java
module JavaIoType
class File
开发者_JS百科class << self
alias_method :old_sp, :separator
def separator(*args)
Kernel.puts caller
old_sp(*args)
end
end
end
end
end
But it doesn't :(
There's also a similar question for clojure. I just wonder if the answer for JRuby would be different.
I know this is bit of a stretch, but I'm asking it anyway.
This works for me (using JRuby 1.6):
require 'java'
java_import 'java.io.File'
puts Java::JavaIo::File::separator
module Java
module JavaIo
class File
class << self
alias_method :old_sp, :separator
def separator(*args)
Kernel.puts caller
old_sp(*args)
end
end
end
end
end
puts Java::JavaIo::File::separator
Outputs:
\
test_io.rb:20:in `(root)'
\
I am not an expert in this, but from my understanding Java methods cannot be redefined from JRuby because its already compiled.
You only have the full freedom in ruby to redefine the methods because of its dynamic nature.
And i believe normal overriding methods through inheritance will work. You can subclass it and override the behavior. But in your case you are redefining static method, so this option also not possible.
But redefining the object methods methods will work with some monkey patching. And these methods are only available to the JRuby.
It works.
require 'rubygems'
require "java"
java_import "java.io.File" do
:JavaFile
end
class JavaFile
alias_method :old_getName, :getName
def getName()
Kernel.puts caller
old_getName()
end
end
x = JavaFile.new('HelloFile.txt')
puts(x.getName())
But:
It works only from the jruby side.
BTW: separator is a static string and not a method.
精彩评论