Project

General

Profile

Actions

Bug #16106

closed

UnboundMethod owner points to base class

Added by sbellware (Scott Bellware) over 3 years ago. Updated about 3 years ago.

Status:
Closed
Priority:
Normal
Assignee:
-
Target version:
-
ruby -v:
ruby 2.6.1p33 (2019-01-30 revision 66950) [x86_64-darwin17]
[ruby-core:94372]

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

unbound_method_owner_sketch.rb (176 Bytes) unbound_method_owner_sketch.rb sbellware (Scott Bellware), 08/15/2019 08:17 PM

Updated by alanwu (Alan Wu) over 3 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) over 3 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) over 3 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 3 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 3 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.

Actions

Also available in: Atom PDF

Like0
Like0Like0Like0Like0Like0