15 May 04:25
Method lookup for modules included in modules
From: Mark Wilden <mark <at> mwilden.com>
Subject: Method lookup for modules included in modules
Newsgroups: gmane.comp.lang.ruby.general
Date: 2008-05-15 02:29:02 GMT
Subject: Method lookup for modules included in modules
Newsgroups: gmane.comp.lang.ruby.general
Date: 2008-05-15 02:29:02 GMT
My question has to do with the diagram on page 12 of "Advanced Rails". It arises from the following structure: module A; end; module B; include A; end module C; include A; end class D; include B; include C; end (This would be a diamond-shaped hierarchy if inheritance were used.) Now picture a similar structure, except without a common ancestor: module A1; end; module A2; end; module B; include A1; end module C; include A2; end class D; include C; include B; end d = D.new When a message is sent to d, that method is searched for in the following order: B, A1, C, A2. My question is how this is implemented in terms of 'klass' and 'super' as described in the book. First, the klass pointer from d takes us to D, whose m_tbl is searched. Then D's super pointer takes us to the proxy for the B module. That proxy's m_tbl pointer points to the B methods which are searched. Then B's super pointer takes us to B's proxy for the A1 module, which causes A1's methods to be search. Here's my problem. If A1 doesn't contain the method, what causes the search to backtrack to the B proxy and follow its super pointer to the C proxy? This "backtracking" seems counter to the purported "linear" lookup order. (This is just a conceptual problem for me - it's obvious what the lookup order is, and it's easy to verify.) The best I can come up with is that the process is this: 1. Look for the method in D 2. If not found, follow the super and look for the method in the B proxy 3. If not found, follow the super and look for the method in the C proxy 4. If not found, follow the super and look for the method in the A2 proxy 5. If not found, give up However, "look for the method in the B proxy" expands to 2a. Look for the method in B 2b. If not found, follow the super and look for the method in the A1 proxy 2c. If not found, give up (which takes us back to #3 above That sounds right. :) But then I'm confused by the use of the klass pointers in the diagram. They seem to imply that when the lookup follows the super from D to the B proxy, that B is a non-class object and hence its klass pointer is used to find its methods. That would imply that the B proxy is an object of the B class, which doesn't sound right. Is the klass pointer actually used to find the B proxy's methods? Or is it just the case that the B proxy class object and the B class object contain the same m_tbl pointer? If so, what (if anything) is the klass pointer between the proxy and the class object used for? I think the best answers to this question will come from people who have the "Advanced Rails" book to hand. I've searched pretty far and wide and simply haven't found an explanation of how method lookup passes from an included module to a module that's included in that one. I'm probably making a conceptual mountain of a molehill, but any clarification (other than "read the code!") would be appreciated. ///ark
RSS Feed