読者です 読者をやめる 読者になる 読者になる

Ruby の alias は評価時点の定義のまま残る

Ruby Gold のサンプル問題を解いてて alias の挙動に関する問題を間違えたので動作確認をした.

ITトレメ Ruby技術者認定【Gold】試験 − @IT自分戦略研究所

class Foo
  def foo
    "foo"
  end
end

class Bar < Foo
  def foo
    super + "bar"
  end
  alias bar foo
  undef foo
end
puts Bar.new.bar

alias と undef

はじめ undeffoo の定義が消されてるので,その foo を参照してる barundefined method になるかなと思ったけど違った.あくまで alias を評価した時点の定義が残るため,bar は実行可能となる.

class Foo
  def foo
    "foo"
  end
end

class Bar < Foo
  def foo
    super + "bar"
  end
  alias bar foo
  undef foo
end
puts Bar.new.bar
# >> foobar

alias と Open Class

Metaprogramming Ruby 2: Program Like the Ruby Pros (Facets of Ruby)

Metaprogramming Ruby 2: Program Like the Ruby Pros (Facets of Ruby)

Metaprogramming Ruby 2 に alias と Open Class の例が載っている.この場合も同じで,alias を評価した時点の定義が残るため,Open Class で再定義しても,旧定義で実行可能となる.P133 に書かれてる説明でスッキリした.

When you redefine a method, you don't really change the method. Instead, you define a new method and attach an existing name to that new method. You can still call the old version of the method as long as you have another name that's still attached to it.

この前読んだときにあまり頭に入ってなかったから読み返せて良かった.

class String
  alias_method :real_length, :length

  def length
    real_length > 5 ? 'long' : 'short'
  end
end

p 'War and Peace'.length
p 'War and Peace'.real_length
# >> "long"
# >> 13

まとめ

勝手に alias をシンボリックリンクのようなものだと勘違いしてて問題を間違えてしまった.もう間違えないぞ!

クラス/メソッドの定義