[Ruby] evil-ruby
コンセプトはわからないけど、become とか superclass= とか
Class#as_module
こんなのないかなぁ。。。と思っていたものがここにあった。
やってることは、おそらくCでの構造体レベルでのデータを変更したりしてる(はず
だけど、dl/structを使ってrubyのみで書かれてるのがすごい。
./test/tc_*.rb 試してみた所、テストが全部通らなかった。
- rprofile付きで実行した時と結果が代わるので、不安定なのかな。
ソースのコメント内にも FIXME memory leak と書いてある。(汗
-
-
- -
-
自分でも数日前に丁度似たような目的のモジュールを書いた事があったので、
その時のコードを載せてみる。
#include "ruby.h" static VALUE mop_set_superclass(self, klass) VALUE self; VALUE klass; { if (TYPE(klass) != T_CLASS) rb_raise(rb_eTypeError, ""); if (RCLASS(self)->super != rb_cObject) rb_clear_cache(); RCLASS(self)->super = klass; return self; } void Init_mop(void) { rb_mMop = rb_define_module("MetaObjectProtocol"); rb_define_method(rb_mMop, "superclass=", mop_set_superclass, 1); }
ruby -rmkmf -e "create_makefile('mop')" && make
#!/usr/bin/env ruby require 'mop.so' Foo = Class.new{define_method("say_hello"){puts "hello, foo"}} Bar = Class.new{define_method("say_hello"){puts "hello, bar"}} c = Class.new(Foo).extend(MetaObjectProtocol) o = c.new o.say_hello # hello, foo c.superclass = Bar # 動的にスーパークラスを変更 o.say_hello # hello, bar
superclassへの代入だけでは、
superclassを何回か変更した時にメソッド名が衝突すると、
cache内の以前のsuperclassのメソッドを呼び出してしまう事があった。
(evilのforumにもpostしてみた)