I was a little surprised, so I will write a code piece and a brief explanation.
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"
As you can see, the call to a1 dynamically defines a2 as an instance method of A. By the way, a2 does not exist unless a1 is called.
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>'
Since a2 is defined as an instance method of A (because it is commonly referenced by an instance of A), it can be called on all objects until the program terminates or is explicitly removed from 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"
By the way, this story can be found in Metaprogramming Ruby 2nd Edition, p111.
Would it be like doing the same thing with 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'
If this is the case, I still feel like I'm doing it forcibly and it's safe (?).