Class#superclass が変わってる

上の記事の追記。

やっぱり 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の仕様ではないそうなので、こういうところに依存しないほうがいいってことだと思いますけど。