UnboundMethod owner points to base class
This may not be a bug. It may be my misinterpretation of the feature.
When using UnboundMethod#owner on a class that was created with
Class.new(SomeBaseClass), the owner is reported as the
SomeBaseClass rather than the new class.
This was a surprising outcome, since I presumed that the owner method would point to the class rather than the class's base class.
class SomeClass def some_method end end C = Class.new(SomeClass) m = C.instance_method(:some_method) pp m.owner # => SomeClass # I would have expected the owner to be C
Is this expected behavior?
Updated by alanwu (Alan Wu) about 4 years ago
Yes, this behavior is expected. Changing it would not be backwards compatible.
I think owner in this case means the entity under which the method is originally defined.
Perhaps the documentation can be improved to reflect this.
Updated by shevegen (Robert A. Heiler) about 4 years ago
I guess the documentation could mention that behaviour so that other
rubyists won't be confused, as alanwu pointed out e. g:
(Or the other documentation site; I just happen to find the above
more readily via a quick google search.)
On a side note, perhaps the name is not ideal, since I can see why
sbellware may be surprised - UnboundMethod implies to me a method
not attached to anywhere, so I was a bit surprised to see that it
still has a pointer to the original class from where it was created
from. Although I understand that this may be useful; it just seems
a bit peculiar to me ... perhaps it is a MostlyUnboundMethod. :P
Updated by sbellware (Scott Bellware) about 4 years ago
Indeed, that's why I was surprised. I wasn't expecting
owner to be a pointer to a class that I wasn't working with.
To correct the code I was working on, I now pass around both the UnboundMethod instance as well as the class, and ignore the
owner method entirely.
I guess what also throws me, from a usability perspective, is that
owner seems asymmetrical with Method#receiver, where Method#receiver is a pointer to the de facto instance that the method is from. I appreciate that this is largely immaterial due to the difference between objects and classes, but just a bit of background on what was informing my biases at the time.
Ideally, it might have been nice to have a method named
implementer on UnboundMethod that does what
owner does, and have
owner reflect some symmetry with Method#receiver. Just a thought.
Updated by jeremyevans0 (Jeremy Evans) about 4 years ago
- Status changed from Open to Closed
The documentation for
Returns the class or module that defines the method.. The example given in the documentation shows
method being called on a Range instance, but having an owner of Enumerable. So I don't think documentation updates are necessary, and this can be closed.
Updated by Eregon (Benoit Daloze) about 4 years ago
An interesting bit here is that there is no way to get back the module from which the method was retrieved, even though it's shown in #inspect:
> Range.instance_method :map => #<UnboundMethod: Range(Enumerable)#map>
Maybe we should expose
UnboundMethod#origin? That would be a separate feature request, though.