From: Robert Klemme Date: 2011-08-22T17:54:15+09:00 Subject: Re: Gritty Details of super() On Sun, Aug 21, 2011 at 10:26 PM, luke gruber wrote: >>extend Mod > > Thanks Gavin and Robert. You're welcome. > Yeah, I knew that extend would do the trick as it includes the instance > methods of the module in the singleton class of the extended object, but > was wondering this: if you include a module that defines a singleton > method, and since the included module 'effectively becomes the > superclass of whatever class included it (pickaxe)', then calls to super > should resolve at the 'effective superclass', no? Care must be taken not to confuse inheritance hierarchies: there are two of them as 7stud has shown with the ASCII graphic. Including a module in a class inserts it into its chain of ancestors, but has no effect on the inheritance hierarchy of the class's singleton class: Basic class: irb(main):001:0> class C;end => nil irb(main):002:0> C.ancestors => [C, Object, Kernel, BasicObject] irb(main):003:0> sc = class < # irb(main):004:0> sc.ancestors => [Class, Module, Object, Kernel, BasicObject] With module included: irb(main):005:0> module M;end => nil irb(main):006:0> class C;include M;end => C irb(main):007:0> C.ancestors => [C, M, Object, Kernel, BasicObject] irb(main):008:0> sc.ancestors => [Class, Module, Object, Kernel, BasicObject] Note how output from lines 2 and 7 differs but not from lines 4 and 8. > On looking into it further though, when a module is included it isn't > 'literally' a superclass, as in all calls to Child.superclass will not > resolve at the included module, even though that module, upon inclusion, > created an anonymous class directly above the class that included the > module. > > In the example that Robert gave above, on line 22 >>22  p Test.superclass > > Right now it's Object, which I understand. But if we also include Mod, > wouldn't that make the superclass of Test some anonymous class that > proxies to Mod? > > But it doesn't... It's still Object. Another confusion that may arise: there are two relations for classes, a superclass relation and an inheritance relation. The superclass relation only ever includes classes and it is fixed at class creation time (by stating "class X < Y" or "Class.new Y") but the inheritance relation includes classes and modules and is modified whenever a module is included somewhere in the class hierarchy. Only the inheritance relation is considered for method lookups. Note: the naming "superclass relation" and "inheritance relation" is not official lingo, I just made it up to have distinguishable names for the two. > So I guess what's weird is that Ruby is creating a superclass when we > include a module, but that superclass is skipped with calls to > superclass. A module cannot be a super/class/. > And when people say that super goes looking in the superclass, that is > not true. It looks in the ancestors, because clearly super can resolve > to anonymous superclasses (included modules, extended modules) as in the > example that Robert gave. Exactly! > hehe, if anyone is still reading this rambling stuff, I appreciate it. It can be confusing at times, especially since everything ultimately inherits Object. This means especially that defining an instance method of Object makes it available to *everything*, i.e. instances, classes and singleton classes. This can sometimes confuse inheritance understanding as well. Kind regards robert -- remember.guy do |as, often| as.you_can - without end http://blog.rubybestpractices.com/