Bug #16106
closedUnboundMethod owner points to base class
Description
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.
Example:
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?
Thanks,
Scott
Files
Updated by alanwu (Alan Wu) about 5 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 5 years ago
I guess the documentation could mention that behaviour so that other
rubyists won't be confused, as alanwu pointed out e. g:
https://ruby-doc.org/core/UnboundMethod.html#method-i-owner
(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 5 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 5 years ago
- Status changed from Open to Closed
The documentation for owner
states: 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 5 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.