Можно ли переопределить классы Java в JRuby?

Как переопределить существующие методы Java в JRuby? Прямо сейчас можно переопределить методы Ruby. Я спрашиваю это, потому что когда вы пишете что-то вроде

include Java

puts java.io.File.separator

и изучите java, io и File, оказывается, что java и io имеют тип «ruby module», а File — это «класс». Поэтому мне было интересно, можно ли написать что-то подобное и ожидать, что это сработает.

module Java
    module JavaIoType
        class File
          class << self
                alias_method :old_sp, :separator
                def separator(*args)
                    Kernel.puts caller
                    old_sp(*args)
                end
            end
        end
    end
end

Но это не так :(

Также есть похожий вопрос для clojure. Мне просто интересно, будет ли ответ для JRuby другим.

Я знаю, что это немного натянуто, но я все равно спрашиваю.


person wiegehtesdir    schedule 23.03.2011    source источник


Ответы (3)


Это работает для меня (используя 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

Выходы:

\
test_io.rb:20:in `(root)'
\
person Sébastien Le Callonnec    schedule 23.03.2011
comment
Да, это работает. Но когда вы добавляете невинную строку, подобную этой puts File.basename("C:\\abc.txt"); (ruby File class), она выдает: NoMethodError: undefined method basename' для Java::JavaIo::File:Class` каким-то образом путает классы ruby ​​и java File. - person wiegehtesdir; 24.03.2011
comment
Кроме того, я также использую JRuby 1.6 и получаю эту ошибку /builtin/javasupport/core_ext/object.rb:99 warning: already initialized constant File У вас нет этой ошибки? - person wiegehtesdir; 24.03.2011
comment
@wiegehtesdir: Ruby File и Java do конфликтуют, вы не можете использовать их взаимозаменяемо или конвертировать один в другой, если честно. Поэтому при использовании Java File лучше использовать полное имя (java.io.File), чтобы избежать этих конфликтов. - person Sébastien Le Callonnec; 24.03.2011

Я не эксперт в этом, но, насколько я понимаю, методы Java нельзя переопределить из JRuby, потому что он уже скомпилирован.

У вас есть полная свобода в ruby ​​только для переопределения методов из-за его динамической природы.

И я считаю, что обычные методы переопределения через наследование будут работать. Вы можете подклассировать его и переопределить поведение. Но в вашем случае вы переопределяете статический метод, поэтому этот вариант также невозможен.

Но переопределение методов методов объекта будет работать с некоторыми исправление обезьяны. И эти методы доступны только для JRuby.

person RameshVel    schedule 23.03.2011

Оно работает.

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())

Но:

Работает только со стороны jruby.

Кстати: разделитель - это статическая строка, а не метод.

person rogergl    schedule 18.07.2012