親の親のメソッドを実行したいが親クラスでオーバーライドされてしまっている時、 気合で親の親のメソッドを呼ぶ方法。
例)class Foo def initialize @name = "foo" end def hello p "Hello:#{@name}"} end end # Fooの子 class Bar < Foo def initialize @name = "bar" end def hello p "hello" end end # Barの子(Fooの孫) class Baz < Bar def initialize @name = "baz" end end foo = Foo.new bar = Bar.new baz = Baz.new foo.hello bar.hello baz.hello # = > "Hello:foo" # => "hello" # => "hello"
Bazの親クラスであるBarクラスでhelloメソッドがオーバーライドされているため Fooクラスのhelloメソッドは実行されない。
FooクラスのhelloメソッドからUnboundMethodオブジェクトを作り、それを介することで 親の親クラスであるFooのhelloメソッドを呼ぶ事ができる。
# FooのhelloメソッドのUnboundMethodを取得 um_hello = Foo.instance_method(:hello) # BazオブジェクトのメソッドとしてFoo#helloを実行 um_hello.bind(baz).call() # => "Hello:baz"
UnboundMethodはレシーバ(どのオブジェクトのものかという情報)を持たないのでUnboundMethod#bindで オブジェクトと結び付けます。 関係ないオブジェクトは結び付けられません。
# omake # Bazの子(Fooのひ孫) class Ubor < Baz def initialize @name = "ubor" end def hello Foo.instance_method(:hello).bind(self).call end end u = Ubor.new u.hello # => "Hello:ubor"
回りくどいけど競合対策で必要になる事もあるかもしれない。
aliasを使って元のメソッドのコピーをとっておくという方法もありますが名前被りがちょっと怖い。