开发者

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.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜