浏览 2428 次
锁定老帖子 主题:JRuby的类重定义……为什么不行?
精华帖 (0) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (0)
|
|
---|---|
作者 | 正文 |
发表时间:2008-06-13
class java.lang.Integer def +(rhs) self.int_value() + rhs end end 但是jirb总是提示self.int_value() + rhs那行有错。到底是为什么呢? 我也就是想这样而已…… irb(main):001:0> i = java.lang.Integer.new(1) # OK irb(main):002:0> i => #<Java::JavaLang::Integer:0x1fbc355 @java_object=1> irb(main):003:0> i.java_class => java.lang.Integer irb(main):004:0> i.int_value => 1 irb(main):005:0> i + 2 # not impl'd => 3 # what I'd like to see 结果我发现我犯了个超低级的错误。JRuby实现java.lang.Integer这样的类型访问实际上是通过method_missing机制,先是对java这个方法进行调用,方法不存在而通过method_missing机制,转换成一个值返回过来;然后对这个返回值调用其lang方法(或者还是说“发送"lang"消息”更合适?),不存在,于是在method_missing里做了点手脚来找到对应的package并返回又一个值,再调用Integer方法,同样是不存在然后通过method_missing找到对应的Java类。 在jirb里试试这个就知道上面说的是什么了: irb(main):001:0> java => Java::Java irb(main):002:0> java() => Java::Java irb(main):003:0> com => Java::Com irb(main):004:0> com().sun() => Java::ComSun 这里的java啊com啊什么的都不是变量,而是不存在的方法而已。 于是,java.lang.Integer只是个会返回一个值的一连串方法调用。Java::JavaLang::Integer才是这个Java类在JRuby里的名字。形式是: 引用 Java::FullPackageNameInCamelCase::ClassName
明白了这点之后,只要把上面的代码改一句就行: irb(main):001:0> class Java::JavaLang::Integer # 改了这里 irb(main):002:1> def +(rhs) irb(main):003:2> self.int_value + rhs irb(main):004:2> end irb(main):005:1> end => nil irb(main):006:0> i = java.lang.Integer.new 2 => #<Java::JavaLang::Integer:0x7efa96 @java_object=2> irb(main):007:0> i + 3 => 5 T T 这种集成方法还是稍微surprise了一下。 不过回过头来想想,IronRuby/DLR的做法跟这个在表现上非常相似,但具体做法不同。JRuby主要通过method_missing机制,而IronRuby/dlr则通过注入全局变量:可以在host里为脚本运行环境注入一个名为System的NamespaceTracker类型全局变量,它会自动找到System下面的各个类以及各个子命名空间。我还是玩DLR的时间更多些,对IronRuby也比对JRuby更熟悉些。可惜现在的IronRuby离真正“能用”差得还好远。 在John Lam的blog上的一篇文章,Dynamic Silverlight Part 3: Integrating Silverlight with ASP.NET MVC里,就有这种要在IronRuby的代码里复写.NET原有类型的方法的使用场景: silverlight.rb: class UIElement alias_method :old_render_transform_origin=, :render_transform_origin= def render_transform_origin=(point) self.old_render_transform_origin = Point.new(point.first, point.last) end end 类名直接就UIElement了(多好 T T UIElement是Silverlight/WPF的一个类。这里是要给RenderTransformOrigin方法写一个adaptor,让它的参数类型从WPF的Point改变为Ruby的数组,让整个类用起来更“Ruby”。很有趣。 当然前面是有相应的require的。JRuby在做了合适的require之后也能达到类似的效果。 声明:ITeye文章版权属于作者,受法律保护。没有作者书面许可不得转载。
推荐链接
|
|
返回顶楼 | |
发表时间:2008-06-16
受教了,不太明白jruby对java类的命名,看到这一句:
Java::FullPackageNameInCamelCase::ClassName 有种恍然大悟的感觉. jruby貌似没有一个正式的文档去说明一下怎么把java集成到jruby中. |
|
返回顶楼 | |
发表时间:2008-06-17
正式的文档我也没见到,不过也不能怪那些在业余时间坚持开发的开发者。
Sun虽然聘请了Thomas Enebo和Charles Nutter,不过整个小组应该还是人力不足吧? 话说这帖原本有个地方有个重要的错误:原帖里我是说java.lang.Integer这样的类型访问中java是一个变量,不过其实不是的。这里java也是一个方法,是一个不存在的方法。上面已经修正更新了…… |
|
返回顶楼 | |
发表时间:2008-06-19
yangzhihuan 写道 受教了,不太明白jruby对java类的命名,看到这一句:
Java::FullPackageNameInCamelCase::ClassName 有种恍然大悟的感觉. jruby貌似没有一个正式的文档去说明一下怎么把java集成到jruby中. wiki上都说的那么详细了,你还要他们怎么说 |
|
返回顶楼 | |
发表时间:2008-06-19
嘛,wiki上那个也算不上正式文档,而且有点过时了。有些已经deprecated的东西还在上面(而没提到deprecated的状态),例如说include_package。
Practical JRuby On Rails Web 2.0 Projects: Bringing Ruby On Rails To Java一书的附录里的介绍至少就比wiki上的新。有机会再写点什么详细点讨论这个。 |
|
返回顶楼 | |