In the below code snippet, I monkey patch Foo#bar
with a define_method
block. After I initialize a new instance of Foo
, I overwrite it with a bind
call to the parent class bar
method, but when I call the method the block defined by the define_method
block is called. Why doesn't the bind
call change the behavior of the method?
class OriginalFoo
def bar
puts 'in OriginalFoo!'
end
end
class Foo < OriginalFoo
def bar
puts 'in Foo'
end
end
class Foo < OriginalFoo
old_bar = instance_method(:bar)
define_method(:bar) do
puts 'in define_method block'
old_bar.bind(self).call
end
end
foo_instance = Foo.new # => #<Foo:0x00007fe3ff037038>
OriginalFoo.instance_method(:bar).bind(foo_instance) # => #<Method: OriginalFoo#bar>
foo_instance.bar
# >> in define_method block
# >> in Foo
You're misunderstanding how UnboundMethod#bind
works. You call Module#instance_method
to get an UnboundMethod
(i.e. a method without a self
):
OriginalFoo.instance_method(:bar)
# #<UnboundMethod: ... >
Then you call UnboundMethod#bind
to attach a self
to that method, that returns a Method
instance:
m = OriginalFoo.instance_method(:bar).bind(foo_instance)
# => #<Method: ...>
But that won't alter the method in foo_instance
, all it does is make self
your foo_instance
when (or if) you said m.call
: um.bind(obj)
doesn't do anything to obj
, it just gives you um
as a Method
that has obj
as its self
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With