From: "David A. Black" Date: 2004-08-11T08:27:29+09:00 Subject: Re: Singleton class methods Hi -- On Wed, 11 Aug 2004, Kyle Putnam wrote: > On Tue, 2004-08-10 at 17:59, Gennady wrote: > > Robert Klemme wrote: > > > > <> > > > > When you have > > > > class Test > > end > > > > You can create constants both in > > > > class Test > > A=45 > > def self.f > > end > > end > > > > and in > > > > class Test > > class << self > > A=45 > > def f > > end > > end > > end > > > > cases. The difference is only where they are visible. > > > > [sparc.titan:13]prod_1> irb > > irb(main):001:0> class Test > > irb(main):002:1> A=45 > > irb(main):003:1> end > > => 45 > > irb(main):004:0> class Test > > irb(main):005:1> A=88 > > irb(main):006:1> end > > (irb):5: warning: already initialized constant A > > => 88 > > irb(main):007:0> class Test > > irb(main):008:1> class << self > > irb(main):009:2> A=55 > > irb(main):010:2> end > > irb(main):011:1> end > > => 55 > > > > NOTE: no warning "already initialized constant A" here. > > > > irb(main):012:0> Test::A > > => 88 > > irb(main):013:0> class Test > > irb(main):014:1> class << self > > irb(main):015:2> A=99 > > irb(main):016:2> end > > irb(main):017:1> end > > (irb):15: warning: already initialized constant A > > => 99 > > > > NOTE: and here we have the warning again. > > > > irb(main):018:0> class Test > > irb(main):019:1> def self.f > > irb(main):020:2> puts A > > irb(main):021:2> end > > irb(main):022:1> end > > => nil > > irb(main):023:0> Test.f > > 88 > > => nil > > irb(main):024:0> class Test > > irb(main):025:1> class << self > > irb(main):026:2> def f2 > > irb(main):027:3> puts A > > irb(main):028:3> end > > irb(main):029:2> end > > irb(main):030:1> end > > => nil > > irb(main):031:0> Test.f2 > > 99 > > => nil > > Your example clears most of this up, for me anyway. However, is there a > way to access this other scope? Obviously Test::A accesses the > non-singleton(?) class's constant. Is this other scope even accessable > from outside the singleton class? > > irb(main):001:0> class << self > irb(main):002:1> CONSTANT = 50 > irb(main):003:1> end > => 50 > irb(main):005:0> self.class::CONSTANT > NameError: uninitialized constant CONSTANT > from (irb):5 > irb(main):006:0> ::CONSTANT > NameError: uninitialized constant CONSTANT > from (irb):6 > irb(main):007:0> class << self > irb(main):008:1> CONSTANT > irb(main):009:1> end > => 50 It's the same as with any class: you can open its scope with the 'class' keyword (using "<< obj" to indicate the anonymous class you want), or you can capture it in a constant or variable and class_eval from there, and so on. For example (using a non-Class object, just for a change of pace :-) x = "hi" class << x C = 1 end xclass = (class << x; self; end) puts xclass::C # => 1 This (class << x; self; end) thing is rather unwieldy, but there's an RCR pending for Kernel#singleton_class, which would then do for an object's singleton class what #class does for its class of origin. Here's that method, plus the above example rewritten to use it: module Kernel def singleton_class; class << self; self; end; end end x = "hi" x.singleton_class::C = 1 # (or const_set if you prefer) p x.singleton_class::C # => 1 David -- David A. Black dblack@wobblini.net