LoginSignup
0
0

More than 5 years have passed since last update.

Rubyのクラスの中でメソッド定義して、その中でメソッド定義すると元のクラスのメソッドになる

Posted at

ちょっとびっくりしたのでコード片と簡単な説明を書いてみます。

sample.rb
class A
  def a1
    def a2
      'a2'
    end
    'a1'
  end
end
output1
irb(main):013:0> obj1 = A.new
=> #<A:0x00000002500198>
irb(main):014:0> obj1.a1
=> "a1"
irb(main):015:0> obj1.a2
=> "a2"

ご覧のとおり、a1の呼び出しでa2がAのインスタンスメソッドとして動的に定義されます。ちなみに、a1を呼びださなければa2は存在しません。

output2
irb(main):009:0> obj2 = A.new
=> #<A:0x000000011b7398>
irb(main):010:0> obj2.a2
NoMethodError: undefined method `a2' for #<A:0x000000011b7398>
        from (irb):10
        from /usr/bin/irb:11:in `<main>'

a2はAのインスタンスメソッドとして定義されるので(Aのインスタンスから共通して参照されるので)、プログラムが終了するか、明示的にAから削除されるまで全てのオブジェクトで呼び出すことができます。

output3
irb(main):009:0> obj3 = A.new
=> #<A:0x00000001106f70>
irb(main):010:0> obj3.a1
=> "a1"
irb(main):011:0> obj3.a2
=> "a2"
irb(main):012:0> obj4 = A.new
=> #<A:0x00000001118888>
irb(main):013:0> obj4.a2
=> "a2"

ちなみに、この話はメタプログラミングRuby第二版、p111に載っています。

同じことをpythonでやるとこうでしょうか?

sample.py
class A:
  def a1(self):
    self.__class__.a2 = lambda cls: 'a2'
    return 'a1'
output4
>>> obj1 = A()
>>> obj1.a1()
'a1'
>>> obj1.a2()
'a2'
>>> obj2 = A()
>>> obj2.a2()
'a2'

これならまだ、無理やりやってる感があって安全(?)な気がしました。

0
0
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0