What is the purpose of having Method#unbind
and UnboundMethod#bind
?
From what I gather, methods are callable objects like procs and lambdas, except that methods are bound to the scope of their receiver:
class SomeClass
def a_method; puts "from SomeClass"; end
end
s = SomeClass.new
s.a_method # => "from SomeClass"
I can call a_method
if I'm within the context of SomeClass
or if I have an object of SomeClass
. I can make it a callable object by extracting the method as a Method
object, yet it's still bound to an object of class SomeClass
in this example:
m = s.method :a_method
m.class # => Method
m.owner # => SomeClass
m.call # => "from SomeClass"
Why would I want to unbind
a method from its receiver? Maybe I can pass this around or bind
it to a different object giving it new context, maybe I can have a completely different object call this method without inheritance, but I can't do anything with it unless I bind it to an object of its original class or I convert it to a Proc
object (really a lambda, since methods and lambdas are somewhat similar):
# Module#instance_method gives me an UnboundMethod
ub = SomeClass.instance_method :a_method
ub.class # -> UnboundMethod
# now I can't make any calls
ub.call # -> NoMethod Error, undefined method 'call'
class AnotherClass; end
a = AnotherClass.new
b = ub.bind(a) # -> TypeError: bind argument must be an instance of SomeClass
b = ub.bind(SomeClass.new).call # -> "from SomeClass"
I could convert the method object into a proc and maybe do something with it:
AnotherClass.class_eval do
# I can access m becausec this block is evaluated in the same
# scope it's defined, so I can grab m ;)
define_method(:method_from_some_class, m.to_proc)
end
AnotherClass.instance_methods(false) # -> [:method_from_some_class]
a.method_from_some_class # -> "from SomeClass"
What is the purpose of doing this? What are the real world applications for something like this?