Hi -- On Fri, 9 Feb 2007, Gary Wright wrote: > > On Feb 8, 2007, at 3:25 PM, oinkoink wrote: >> That is, each class in an inheritance tree can get a variable >> which refers to itself and >> all its descendents. Class-tree variables are implemented by class >> variables, but the >> implementation occurs only in the top (root) class and is inherited by >> the rest of the tree. > > Ruby's class variables already have this behavior, sort of. > The gotcha is that order matters. More info after the example... Also you wouldn't want to use class variables to maintain state for a class, since they're considered the property equally of all the instances. > class A; end > class B < A; end > > class A; @@alpha = 42; end # establishes @@alpha for A and descendants > class B; @@alpha = 52; end # reuses @@alpha from A > class A; @@alpha; end # 52 > class B; @@alpha; end # 52 > > ################# > > class C; end > class D < C; end > class E < C; end > class D; @@beta = 42; end # establishes @@beta for B and descendants > class C; @@beta = 52; end # establishes @@beta for A and descendents > # *excluding* B since that branch already > # has @@beta defined! I think there's an error here; C and D aren't related to A and B. > class C; @@beta; end # 52 > class D; @@beta; end # 42 > class E; @@beta; end # 52 > > > There are three issues that make Ruby's class variables obtuse: > > 1) The inheritance tree lookup procedure described above. > 2) The lexical scoping used to initiate the lookup (see below). > 3) The name 'class variable', which has a much different meaning > in Ruby than in other languages because of 1) and 2) 4) The @@ prefix, which leads people to think there must be some similarity or kinship with instance variables. Class variables would be better off using $$, because they're more closely related to globals than to instance variables. > Lexical Scoping > > The starting class for class variable name resolution (step 1) is > determined lexically (e.g., by the parser) not dynamically: > > $ cat lexical.rb > class A > @@alpha = 42 # lexically within A, @@alpha anchored to A > end > > @@alpha = 52 # lexically in top-level, @@alpha anchored to Object > > p (class Object; @@alpha; end) # 52 > p (class A; @@alpha; end) # 42 > > p A.class_eval { @@alpha } # 52! lexically at top-level, not A! I think the scope of class_eval is pretty much flat with the scope it's created in, even for constants and class variables. > def A.show_alpha > @@alpha # lexically at top-level!!! > end > p A.show_alpha #52! I'm not sure whether it's lexical scoping or just the fact that A's singleton class is sharing @@alpha with Object. If you do: class String p @@alpha end you'll also get 52. Also, if you do: class << A @@alpha = 1 end p @@alpha Object's @@alpha will be 1. David -- Q. What is THE Ruby book for Rails developers? A. RUBY FOR RAILS by David A. Black (http://www.manning.com/black) (See what readers are saying! http://www.rubypal.com/r4rrevs.pdf) Q. Where can I get Ruby/Rails on-site training, consulting, coaching? A. Ruby Power and Light, LLC (http://www.rubypal.com)