undef_methodはクラスにメソッドを追加する?
Module#undef_methodを使うと、「親クラスのメソッドは子クラスで未定義にできる。子クラスで未定義にしたメソッドを孫クラスから呼ぶと未定義になる」ということに気づきました。つまり、「孫→子→親」とメソッドを探すとき、子をスルーして親のメソッドを呼ぶのではなく、子の「未定義」にぶつかるということです。
動作としては自然ですが、どうなっているのでしょう。
class Parent def greet() "hello" end end class Child < Parent undef_method :greet end class GrandChild < Child end p GrandChild.new.respond_to?(:greet) #=> false
以下はRuby 1.9.1-p376のvm_method.cの関数rb_undef。クラスklassに名前がidで内容が0のメソッドを加えています。これは「同名で呼び出せないメソッド」を新たに加えているのではないだろうか(あまり自信なし)。
476 void 477 rb_undef(VALUE klass, ID id) 478 { (中略) 515 rb_add_method(klass, id, 0, NOEX_PUBLIC);
Module#privateも、親のメソッドを子でprivateにできます。この場合は、privateメソッドが「名前と内容が同じでprivateフラグが立ったメソッドを子に加える」ことをprivate_instance_methods(false)で確認できます。
class Parent def greet() "hello" end end class Child < Parent private :greet end p Child.private_instance_methods(false) #=> [:greet]
Module#alias_methodもまた、新しいメソッドを加えるメソッドで、「名前が別で内容が同じものを指すメソッドを加える」であると思われます。
class Parent def greet() "hello" end end class Child < Parent alias_method :orig_greet, :greet end p Child.public_instance_methods(false) #=> [:orig_greet]
元メソッドを削除・未定義・上書きしても、別名メソッドは同じ機能を保持します。これは、元メソッドの内容は消されず、別名メソッドが元メソッドの内容を指したままである、ということなのでしょう。