From: Robert Klemme Date: 2010-06-07T23:18:59+09:00 Subject: Re: Singleton classes and Namespce 2010/6/7 Caleb Clausen : > On 6/7/10, Robert Klemme wrote: >> 2010/6/6 Intransition : >>> Do singleton classes not get the same namespace treatment as normal >>> classes? >> >> I think so. >> >>>  module M >>>    class X; end >>>  end >>> >>>  o = Object.new >>>  => # >>> >>>  (class << o; self; end).class_eval{ include M } >>>  => # >>> >>>  def o.x; X; end >> >> This cannot work since X is not statically in scope. > > Ah, but constant lookup is supposed to check the ancestors if the > constant is not found in the scope. M should be among the ancestors of > o's singleton class, shouldn't it? It does but you are not in the scope of the singleton class. Rather you are in the toplevel (or any other) scope when you do "def o.x; X; end". > I would have expected this to work. > OTOH, constant lookup is confusing. > > This way works: > >  module M >   class X; end >  end > >  o = Object.new  # => # > >  (class << o; self; end).class_eval{ include M } # => # >  #or o.extend M as well, presumably > >  class<    def x; X end >  end > >  o.x   #=>M::X That's basically the same what I did: you create the method in the singleton class's scope. > See http://ruby.runpaint.org/variables#constants in which the lookup > rules are summarized as: >  (Module.nesting + container.ancestors + Object.ancestors).uniq > #slightly paraphrased > > I guess the key point to understand is that for singleton methods, > container is the (static) module of class enclosing the singleton > method, NOT the singleton class that they affect. Not sure I can follow you here. IMHO the key point is to understand that it is a difference whether you open a scope (class, module) or access the scope from the outside: irb(main):001:0> module M irb(main):002:1> class X; end irb(main):003:1> O = Object.new irb(main):004:1> end => # irb(main):005:0> def (M::O).x; X; end => nil irb(main):006:0> M::O.x NameError: uninitialized constant X from (irb):5:in `x' from (irb):6 from /opt/bin/irb19:12:in `
' irb(main):007:0> module M irb(main):008:1> def O.y; X; end irb(main):009:1> end => nil irb(main):010:0> M::O.y => M::X irb(main):011:0> def (M::O).x; M::X; end => nil irb(main):012:0> M::O.x => M::X Kind regards robert -- remember.guy do |as, often| as.you_can - without end http://blog.rubybestpractices.com/