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)