From: "David A. Black" Date: 2005-11-27T06:44:00+09:00 Subject: Re: Nubish questions about syntax and gems Hi -- On Sun, 27 Nov 2005, Sean O'Halpin wrote: > This is a little test that (to me) shows how wacky the scoping rules > are for class variables: > > class A > @@foo = "class variable foo" > @foo = "class instance variable foo" > def self.evaluate(txt) > instance_eval txt > end > def self.eval_block(&block) > instance_eval &block > end > end > > begin > p A.instance_eval { @@foo } > rescue => e > puts e > end > > @@foo = "hi" > > p A.instance_eval { [self, @@foo, @foo] } > p A.evaluate("[self, @@foo, @foo]") > p A.eval_block { [self, @@foo, @foo] } > > class B > @@foo = "B's class variable foo" > @foo = "B instance foo" > def self.eval_block(&block) > instance_eval &block > end > end > > p B.eval_block { [self, @@foo, @foo] } > __END__ > uninitialized class variable @@foo in Object > [A, "hi", "class instance variable foo"] > [A, "class variable foo", "class instance variable foo"] > [A, "hi", "class instance variable foo"] > [B, "B's class variable foo", "B instance foo"] > > I'd be grateful if anyone can explain this behaviour (i.e. why the > call to B.eval_block gets B's class variable but the call to A gets > the outer scope). What you've got basically is: class A @@foo = "A's class variable foo" end @@foo = "Object's class variable foo" class B @@foo = "B's class variable foo" end Since B is a subclass of Object, setting B's @@foo also sets Object's @@foo. The reason A's @@foo (when you see it via the instance eval) does not change is that if you create a subclass's class variable *first*, and then the superclass's (in this case, A and Object, respectively), they are separate: irb(main):002:0> class A; end; class B < A; @@foo = 1; end; class A; @@foo = 2; puts @@foo; end 2 => nil irb(main):003:0> class B; puts @@foo; end 1 David -- David A. Black dblack@wobblini.net