From: Gary Wright Date: 2007-02-09T06:13:59+09:00 Subject: Re: Class-tree variables 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... 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! 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) 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! def A.show_alpha @@alpha # lexically at top-level!!! end p A.show_alpha #52! $ ruby lexical.rb 52 42 52 52 ######################################## $ cat lexical2.rb @@alpha = 52 # lexically in top-level, @@alpha anchored to Object class A @@alpha = 42 # lexically within A, @@alpha anchored to A # *but* @@alpha already defined in ancestor (Object) # so @@alpha from Object is referenced end p (class Object; @@alpha; end) # 42 p (class A; @@alpha; end) # 42 $ ruby lexical2.rb 42 42 Gary Wright