That statement does not make sense to me as indicated above.
I think perhaps our mental models of Ruby are incompatible. One final thought.
I am suspecting it is rather different usage of terms.
The
hierarchical relationship between classes is an inheritance
relationship via #superclass. The relationship between objects and
classes is that of instantiation via #instance_of?.
What, then, is this?
[1] pry(main)> class Foo; end
=> nil
[2] pry(main)> module Bar; end
=> nil
[3] pry(main)> x = Foo.new.extend(Bar)
=> #<Foo:0x000000037df598>
[...]
[7] pry(main)> x.singleton_class.ancestors
=> [#<Class:#<Foo:0x000000037df598>>, Bar, Foo, Object, PP::ObjectMixin, Kernel, BasicObject]
When Ruby tries to find a method, it walks up a **single hierarchy** of objects. It starts with the current object,
No. It starts with the singleton class. If you look at
rb_search_method_entry() you'll notice that obtaining the class is the
first thing the method does:
https://github.com/ruby/ruby/blob/trunk/vm_eval.c#L526
If you are interested how I got there:
1. find -type f -name \*.c -exec egrep 'rb_define_method.*send' {} +
./vm_eval.c:2205: rb_define_method(rb_mKernel, "send", rb_f_send, -1);
2. rb_f_send() in vm_eval.c
https://github.com/ruby/ruby/blob/trunk/vm_eval.c#L979
3. rb_send_internal() in vm_eval.c
https://github.com/ruby/ruby/blob/trunk/vm_eval.c#L899
4. rb_call0() in vm_eval.c
https://github.com/ruby/ruby/blob/trunk/vm_eval.c#L331
then looks in the singleton class of the object, then the parents of that singleton class, then the parent class of the object, then the singleton class of that class and so on: one hierarchy involving the current object and any other number of classes, modules, singleton classes and (admittedly this would be pretty weird?) other objects.
The method lookup is more like this:
1. Look in singleton class of instance
2. Look in modules included in singleton class of instance in reverse
inclusion order
3. Look in super class of singleton class which happens to be the
"official" class of the instance
4. Look in modules included in class of instance in reverse inclusion order
5. loop to step 3 with the super class of the current class looked at
until method or end of class hierarchy found
Actually steps 1 and 3 and 2 and 4 are the same so you could condense
this to three steps. Just listed for more clarity. You can see this
order by doing obj.singleton_class.ancestors - that gives you the
order in which classes and modules are traversed.
With refinements things get more complicated.
http://ruby-doc.org//core-2.2.0/doc/syntax/refinements_rdoc.html
You can, of course, view things in terms of a separate class inheritance hierarchy if you wish. In other languages this is literally true. But really, Ruby isn't _quite_ working like that.
The fact that anything is an object in Ruby (which is good and allows
to do quite some cool things, btw.) does not mean that mere objects
which are not instances of Class or Method are part of the inheritance
hierarchy. There is no generic object hierarchy that plays a role in
method lookup. It's all classes and modules.
Cheers
robert
···
On Mon, Nov 14, 2016 at 4:14 PM, Andy Jones <Andy.Jones@jameshall.co.uk> wrote:
--
[guy, jim, charlie].each {|him| remember.him do |as, often| as.you_can
- without end}
http://blog.rubybestpractices.com/