2009-11-04 27 views
2

從Java加載的JRuby類我在Java代碼下面的類:通過的Class.forName

public class CHRTreeCreator extends IndexCreator { ... } 

相反CHRTreeCreator我想用不同勢執行這也延伸IndexCreator,但我想它在JRuby的代碼。問題是,中IndexCreator具體實現是基於XML配置文件選擇:

<creator>dwe.index.tree.chr.CHRTreeCreator</creator> 

的代碼如下所示:

// className is fetched from XML 
Class creatorClass = Class.forName(className); 
Constructor constructor = creatorClass.getConstructor(new Class[] { }); 
creator = (IndexCreator) constructor.newInstance(new Object[] { }); 

的問題是,是否有可能實現它在Ruby中,像這個:

class MyIndexCreator < IndexCreator 
end 

以某種方式把MyIndexCreator類名放入XML配置文件。在這種情況下,模塊包映射如何工作?

如果不能通過Java的Class.forName加載Ruby類,我該如何解決這個問題?

回答

5

目前JRuby的子類是不可訪問通過Java以這種方式,雖然它在某些能力爲未來實現計劃(JRuby的1.5也許)。

一種選擇(取決於你的類的API)是創建一個委託:

public class RubyIndexCreator extends IndexCreator { 
    private IndexCreator rubyCreator; 
    public RubyIndexCreator() { 
    ScriptEngineManager factory = new ScriptEngineManager(); 
    ScriptEngine engine = factory.getEngineByName("ruby"); 
    FileReader r = new FileReader("ruby_index_creator.rb"); 
    try { 
     rubyCreator = engine.eval(r); 
    } 
    finally { 
     r.close(); 
    } 
    } 

    public Object create(String someArg) { 
    return rubyCreator.create(someArg); 
    } 
} 

我已經掩蓋了緩存一些機會,也只是勾勒出管理文件閱讀器,但希望你得到的照片。

在這個特殊的例子,ruby_index_creator.rb將實現您的索引創建類,然後返回它的一個實例 - 顯然從這裏可以參考其他Ruby文件,並酌情安排:

class MyIndexer < IndexCreator 
[...] 
end 
MyIndexer.new 

這就是它!

0

作爲一種選擇,也許您可​​以利用Ruby的Open Classes並直接修改CHRTreeCreator的行爲(而不是子類別)。

+0

感謝羅布,該解決方案可以在我的情況下以某種方式工作(而且我現在確實這樣做),但我不想猴子修補Java類。應該有一些通用的方法來使用.forName方法加載Ruby類,對吧? – 2009-11-08 19:57:06

0

如何使用Ruby的eval:

C:\>jirb 
irb(main):001:0> require 'java' 
=> false 
irb(main):002:0> class MyDate < Java::JavaUtil::Date 
irb(main):003:1> def my_method;puts "hi there";end 
irb(main):004:1> end 
=> nil 
irb(main):005:0> 
irb(main):006:0* c = "MyDate" 
=> "MyDate" 
irb(main):007:0> obj = eval("#{c}.new") 
=> #<MyDate:0xd2efa1> 
irb(main):008:0> obj.my_method 
hi there 
=> nil 
irb(main):009:0>