luke gruber wrote in post #1017884:
The question is: Why isn't M's singleton class inserted into the
singleton class hierarchy?
As to why that is? I have no idea. Things would be nice and
symmetrical if a module's singleton class did get inserted in the
singleton class hierarchy.
(The method lookup diagrams were copied from Metaprogramming Ruby.)
7stud
Thanks 7stud, that was exactly what I was trying to get at.
The confusion I have with the current approach is this:
If Ruby wanted us to forget about the whole anonymous superclass
proxying the module on inclusion or extension, then in order for the
module (which, in our mental makeup in this case is right above the
class that included/extended the module), it would make the most sense
for singleton methods called on our class to resolve/lookup the module's
singleton methods upon a method_missing or super or whatever.
However, this is not the case as we all know.
So OK, maybe Ruby wants us to KNOW about the anonymous superclass that
is proxying the module, and for this to not only be an implementation
feature/hack, but a feature of the language that we can put in our
mental model of method lookup. But if we put this in our mental model,
then a couple of problems arise for me.
First, ::ancestors. ::ancestors shows the module name, which is nice,
but crumples our mental model a bit as it should show the anon
superclass if our mental model was changed.
I don't think changing the name 'M' to 'anon-M', or even worse: "",
would make much difference. You just have to know that superclass()
doesn't return included modules, and ancestors does.
The second
problem/misunderstanding for me is that the anonymous superclass that
proxies the module (ASCTPTM...hehe)
does not proxy the singleton methods of the module.
I think you aren't making the correct distinction here: there are two
classes not one. When you include a module, ruby creates an anonymous
class containing the module's instance methods, which are defined like
this:
module M
def eat
puts 'munch, munch'
end
end
...and ruby also creates a singleton class containing the module's
singleton methods, which are defined like this:
module M
M.greet
puts 'MMMM'
end
end
In all situations in ruby, the singleton methods are not in the same
class as the instance methods. For instance, if you do this:
class Dog
def Dog.greet
puts 'hello'
end
def speak
puts 'woof, woof'
end
end
That doesn't create just one class. ruby creates two classes: Dog and
#Dog, which are in two different lookup hierarchies--as the lookup
diagram shows. Therefore, your statement here:
the anonymous superclass that
proxies the module (ASCTPTM...hehe)
does not proxy the singleton methods of the module.
is non-sensical because a regular class (or an anonymous class) never
contains the singleton methods.
This stuff isn't easy to understand, but you can make some sense of
things. However, I find the following totally unhelpful:
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 <<C;self;end
=> #<Class:C>
irb(main):004:0> sc.ancestors
=> [Class, Module, Object, Kernel, BasicObject]
Note that sc.ancestors does not list any of the singleton classes as
detailed in the lookup diagram.
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]
So how does that result prove that including a module does nothing to
the lookup diagram? sc.ancestors never listed the singleton classes in
the first place, and after including the module sc.ancestors still
doesn't list the singleton classes.
···
--
Posted via http://www.ruby-forum.com/\.