
Submitted by flgr (Mon Feb 14 21:02:06 UTC 2005)
I can not think of an actual sample of what Method#target could be used for right now, but I think it would not hurt to add it either. It's the one that could be removed from this RCR most easily.
The effort to implement this ought to be fairly low as the structs already contain the information anyway. (UnboundMethod#inspect uses it.)
#origin would return the Class or Module where the (Unbound)Method was originally defined. #name would return the original method name as either a String or Symbol. (I prefer Symbol) #target would return the bind target -- the Object the Method is bound to.
It's not so easy with method.origin -- it can be done in case the origin was not an anonymous Module or Class, but it requires a bit more Regexp work and using the module_name.split("::").inject(Object) { |mod, item| mod.const_get(item) } trick.
Method#target can not be implemented at all in pure Ruby as far as I know.
In the proposal I mentioned possibly renaming #name to #original_name -- this is because the #name might already be reused for another method at the time the call is made or not be used at all. See this code sample for when this would happen:
class Foo
def x() 1 end
end
old_x = Foo.instance_method(:x)
class Foo
remove_method :x
# old_x.name still returns :x, but old_x.origin.instance_method(old_x.name) raises an Exception
def x() 2 end
# old_x.name still returns :x, but old_x.origin.instance_method(old_x.name).bind(obj).call != old_x.bind(obj).call
end
I don't think that the behavior is much of a problem when pointed out in the documentation, but I thought pointing it out would be a good idea.

| Comments | Current voting | ||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|
|


RCRchive copyright © David Alan Black, 2003-2005.
Powered by .
The Object#__id__ and Object#__send__ methods are named that way because of the enourmously dense namespace they inhabit. For instance, an object representing an XML element might want to define an #id method, and an object representing a network socket might want to define #send. I see no point in using the name Method#__name__, since we don't expect people to subclass Method and define a #name method of their own. It would make about as much sense as Module#__define_method__, Proc#__call__, or even String#__split__.
Could someone explain these better. Primarily what is #target?
#target simply returns the object the method is bound to. 5.method(:+).target would return 5.
Yes, so if we: a = Klass.new b = a.method: name b.target => would return the object that 'a' points to. b.origin => would return Klass.
++ On this one! I logged into RCR to suggest the exact same thing in fact :-p.
I've implemented these methods in Nodewrap. Here's the relevant C implementation. Method#target corresponds to method_receiver, Method#name corresponds to either method_id or method_oid (depending on whether you want the current or original name), and Method#origin corresponds to method_origin_class:
/* * Given a Method, returns the Object to which it is bound. */ static VALUE method_receiver(VALUE method) { struct METHOD * m; Data_Get_Struct(method, struct METHOD, m); return m->recv; } /* * Given a Method, returns the Symbol of the method it represents. If * the method is an alias for another method, returns the Symbol of the * new method, not the original. If the method changes name, returns * the original name, not the new name. */ static VALUE method_id(VALUE method) { struct METHOD * m; Data_Get_Struct(method, struct METHOD, m); return ID2SYM(m->id); } /* * Given a Method, returns the Symbol of the method it represents. If * the method is an alias for another method, returns the Symbol of the * original method, not the alias. If the original method changes name, * returns the original name. */ static VALUE method_oid(VALUE method) { struct METHOD * m; Data_Get_Struct(method, struct METHOD, m); return ID2SYM(m->oid); } /* * Given a Method, returns the Class in which the method it represents * was defined. If the method was defined in a base class and * Object#method is called on a derived instance of that base class, * this method returns the base class. */ static VALUE method_origin_class(VALUE method) { struct METHOD * m; Data_Get_Struct(method, struct METHOD, m); #if RUBY_VERSION_CODE < 180 return m->oklass; #else return m->rklass; #endif }-- Paul Brannan