Ruby メタプログラミングの初心者です。irb でコードを練習しているときに、この問題に遭遇しました。
class A; end
a = A.new
b = class << a; self; end
b.instance_eval { def foo; puts 'foo'; end }
# => works for b.foo
b.instance_eval { define_method :bar do; puts 'bar'; end }
# => WHY this one works for a.bar rather than b.bar
最後のコード片は私を混乱させました。
具体的な回答をありがとうございますが、混乱を明確に説明していない可能性があります。私が本当に理解しようとしているのはdefine_method
、これらの場合になぜ動作が異なるのかということです。
class A
def foo1
p 'foo1 from A'
end
define_method :bar1 do
p 'bar1 from A'
end
end
a = A.new
a.foo1 # => 'foo1 from A'
a.bar1 # => 'bar1 from A'
a.instance_eval { def foo2; p 'foo2 from a.metaclass'; end }
a.foo2 # => 'foo2 from a.metaclass'
a.instance_eval { define_method :bar2 do; p 'bar2 from a.metaclass'; end }
# => NoMethodError: undefined method `define_method' for #<A:0x000000016a2e70>
aa = class << a; self; end
aa.instance_eval { def foo3; p 'foo3 from a.metaclass.metaclass'; end }
aa.foo3 # => 'foo3 from a.metaclass.metaclass'
aa.instance_eval { define_method :bar3 do; p 'bar3 from a.metaclass.metaclss'; end }
aa.bar3 # => NoMethodError: undefined method `bar3' for #<Class:#<A:0x000000016a2e70>>
a.bar3 # => 'bar3 from a.metaclass.metaclss'
これは日常のコーディングでは出てこないことはわかっていますが、はっきりさせておきたいと思います。
結論を出す:
aa = class << a; self; end
aa.instance_eval { def foo; puts 'foo..'; end }
# defines a singleton-method for aa
aa.foo # => 'foo...'
aa.instance_eval { define_method :bar do; puts 'bar..'; end }
# equals
aa.class_eval { def bar; puts 'bar..'; end }
# both define a singleton-method for a,
# as define_method and class_eval both define instance_method
a.bar # => 'bar...'