按Class.forName从Java加载JRuby类

按Class.forName从Java加载JRuby类,java,jruby,classloader,Java,Jruby,Classloader,我有以下Java代码类: public class CHRTreeCreator extends IndexCreator { ... } 相反,CHRTreeCreator我想使用不同的实现,它也扩展了IndexCreator,但我想在JRuby中对其进行编码。问题是,IndexCreator的具体实现是基于xml配置文件选择的: <creator>dwe.index.tree.chr.CHRTreeCreator</creator> 问题是,是否可以在Ruby中实

我有以下Java代码类:

public class CHRTreeCreator extends IndexCreator { ... }
相反,
CHRTreeCreator
我想使用不同的实现,它也扩展了
IndexCreator
,但我想在JRuby中对其进行编码。问题是,
IndexCreator
的具体实现是基于xml配置文件选择的:

<creator>dwe.index.tree.chr.CHRTreeCreator</creator>
问题是,是否可以在Ruby中实现它,如下所示:

// className is fetched from XML
Class creatorClass = Class.forName(className);
Constructor constructor = creatorClass.getConstructor(new Class[] {  });
creator = (IndexCreator) constructor.newInstance(new Object[] { });
class MyIndexCreator < IndexCreator
end
类MyIndexCreator
并以某种方式将
MyIndexCreator
类名放入XML配置文件中。在这种情况下,模块包映射是如何工作的


如果无法通过Java的Class.forName加载Ruby类,我应该如何解决这个问题

另一种选择是,您可以利用Ruby的开放类,直接修改chrtecreator的行为(而不是子类)。

使用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>
C:\>jirb
irb(主):001:0>需要“java”
=>错误
irb(main):002:0>classmydate定义我的方法;把“你好”;终止
irb(主):004:1>结束
=>零
irb(主要):005:0>
irb(主):006:0*c=“我的日期”
=>“我的日期”
irb(main):007:0>obj=eval(“{c}.new”)
=> #
irb(main):008:0>obj.my_方法
你好
=>零
irb(主要):009:0>

目前,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\u index\u creator.rb
将实现您的index creator类,然后返回它的一个实例-显然,您可以从这里引用其他ruby文件,并根据需要组织:

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

就这样

感谢Rob,这个解决方案在我的情况下可以起到一定的作用(我现在确实是这样做的),但我不希望对Java类进行猴子补丁。应该有一些通用的方法来使用.forName方法加载Ruby类,对吗?