使い方
classとdefは実際には実行可能なコードであるため、Ruby では実行時にクラスを再定義できます。あなたの例では、コードは次のことを行います。
- インスタンス メソッドが呼び出されたときに Example#one メソッドを (再) 定義する Example#one メソッドを定義します。
- 実際には、外側のインスタンス メソッドが呼び出されるまで、内側の定義は実行されません。(理不尽な人はこの定義を正当に主張するかもしれませんが、それはこの議論の目的には関係のないパーサー/インタープリターの詳細に入ります。)
- 「ex」という名前の Example のインスタンスを定義します。
- exでインスタンス メソッドを呼び出します。これにより、同じ名前の新しいメソッドが定義されます。
- インスタンス メソッドを再度呼び出すと、古いメソッドの代わりに新しいメソッドが使用されます。
機能する理由
基本的に、メソッドの最後の定義はその名前空間の以前の定義を置き換えますが、メソッドは実際には新しいオブジェクトです。これは、次のように実際に確認できます。
def my_method
puts 'Old Method'
puts self.method(:my_method).object_id
def my_method
puts 'New Method'
puts self.method(:my_method).object_id
end
end
これを irb または pry セッションで実行すると、実行時にメソッドが再定義されていることがわかります。
> my_method; puts; my_method
Old Method
8998420
New Method
8998360
異なるオブジェクト ID からわかるように、メソッドは同じ名前を持ち、同じオブジェクト (通常はコンソールのメイン) にアタッチされていますが、実際には異なるメソッド オブジェクトです。ただし、メソッドは同じ名前で定義されているため、インスタンスがメソッド ルックアップを実行すると、最新の定義のみが検出されます。