上の記事の追記。
やっぱり Class#superclass が変化しているようです。
これが 1.8.6 の実装。
static VALUE rb_class_superclass(klass) VALUE klass; { VALUE super = RCLASS(klass)->super; if (!super) { rb_raise(rb_eTypeError, "uninitialized class"); } if (FL_TEST(klass, FL_SINGLETON)) { super = RBASIC(klass)->klass; } while (TYPE(super) == T_ICLASS) { super = RCLASS(super)->super; } if (!super) { return Qnil; } return super; }
特異クラスの時には super のかわりになぜか klass を辿るようになっています。1.9 では 2つめの if 文がなくなっています。
従って上の記事の 1. 2. は、Rubyからはそうみえるけど実体は変化していないよーってことでした。
それにしても Class#superclass はなんでこんなふうになってたんでしょうね。1.9 の実装のほうが素直ですし、こんなことをしてみたら違いがよくわかります。
class A; end a = A.new a_eigenclass = class << a; self; end a_eigenclass.superclass.module_eval <<-EOF def hoge puts "hoge" end EOF begin A.hoge rescue puts "A.hoge raise : #{$!}" end begin a.hoge rescue puts "a.hoge raise : #{$!}" end
1.8.6 なら a.hoge が例外になり、1.9(trunk)は A.hoge が例外になります。
a_eigenclass.superclass にメソッド追加する時にどっちかといえば1.9の挙動を期待するような気がしますが、どんなもんでしょうね。まあ特異クラスは公式なRubyの仕様ではないそうなので、こういうところに依存しないほうがいいってことだと思いますけど。