# Class-tree variables

**URL:** <https://www.ruby-forum.com/t/class-tree-variables/84959>\
**Category:** Ruby\
**Created:** [February 8, 2007, 9:27pm UTC](https://www.ruby-forum.com/t/class-tree-variables/84959 "2007-02-08T21:27:09Z")\
**Posts on this page:** 7\
**Page:** 1

<div class="post-metadata">

**Author:** ![oinkoink](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/o/8e8cbc/32.png) [@oinkoink](https://www.ruby-forum.com/u/oinkoink)\
**Post date:** [February 8, 2007, 9:27pm UTC](https://www.ruby-forum.com/t/class-tree-variables/84959/1 "2007-02-08T21:27:09Z")

</div>

There’s been a lot of blog traffic lately about class variables vs.  
class instance variables.  
I’d like to give an example of something in-between: class-tree  
variables. These are sort  
of like class variables, but they only point downward in the  
inheritance tree rather than  
up. 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.  
It is probably unclear what the heck I am talking about, but the  
following example should  
make things clear.

# class\_tree\_var.rb: demo program of class-tree variables

#-- Hey Emacs! Use -_- mode: ruby; coding: utf-8-unix; -_-  
class Person  
attr\_accessor :name

class \<\< self  
attr\_writer :instances  
def instances  
@instances ||= []  
end  
end

def initialize( name )  
klass = self.class  
until klass == Person  
klass.instances \<\< self  
klass = klass.superclass  
end  
Person.instances \<\< self  
@name = name  
end

end

class Scholar \< Person  
end  
class Student \< Scholar  
end  
class Professor \< Scholar  
end  
%w(Fred Barney).each{|caveman| Person.new(caveman)}  
%w(Wilma Betty).each{|cavewoman| Scholar.new(cavewoman)}  
%w(Twerply Bob Sheila).each{|brat| Student.new(brat)}  
%w(Whiplash Grindemdown).each{|sadist| Professor.new(sadist)}  
puts "Persons are " + Person.instances.collect{|person|  
person.name}.join(’, ‘)  
puts "Scholars are " + Scholar.instances.collect{|scholar|  
scholar.name}.join(’, ‘)  
puts "Students are " + Student.instances.collect{|student|  
student.name}.join(’, ‘)  
puts "Professors are " + Professor.instances.collect{|professor|  
professor.name}.join(’, ')

# end of file

$ ruby class\_tree\_var.rb  
Persons are Fred, Barney, Wilma, Betty, Twerply, Bob, Sheila,  
Whiplash, Grindemdown  
Scholars are Wilma, Betty, Twerply, Bob, Sheila, Whiplash, Grindemdown  
Students are Twerply, Bob, Sheila  
Professors are Whiplash, Grindemdown

I don’t actually recommend this. I think that in Ruby it’s better not  
to use inheritance for  
such things; you have an abundance of alternatives that are more  
flexible. Functionality  
built into inheritance tends to break upon refactoring. But I think  
this example does shed  
some light on what class instance variables are capable of. It did  
for me, anyway.

Regards, Bret  
Bret Jolly

---

<div class="post-metadata">

**Author:** ![oinkoink](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/o/8e8cbc/32.png) [@oinkoink](https://www.ruby-forum.com/u/oinkoink)\
**Post date:** [February 8, 2007, 9:42pm UTC](https://www.ruby-forum.com/t/class-tree-variables/84959/2 "2007-02-08T21:42:10Z")

</div>

Hi –

On Fri, 9 Feb 2007, oinkoink wrote:

> There’s been a lot of blog traffic lately about class variables vs.  
> class instance variables. I’d like to give an example of something  
> in-between: class-tree variables. These are sort of like class  
> variables, but they only point downward in the inheritance tree  
> rather than up. 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.

I think that’s a typo; I don’t see any class variables in your code.

> def instances  
> Person.instances \<\< self  
> end  
> puts "Professors are " + Professor.instances.collect{|professor|  
> I don’t actually recommend this. I think that in Ruby it’s better  
> not to use inheritance for such things; you have an abundance of  
> alternatives that are more flexible. Functionality built into  
> inheritance tends to break upon refactoring. But I think this  
> example does shed some light on what class instance variables are  
> capable of. It did for me, anyway.

It’s a good illustration of the fact that instance variables are the  
way to maintain state per object, and that that’s the same for class  
objects as for other objects.

David

---

<div class="post-metadata">

**Author:** ![oinkoink](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/o/8e8cbc/32.png) [@oinkoink](https://www.ruby-forum.com/u/oinkoink)\
**Post date:** [February 8, 2007, 9:51pm UTC](https://www.ruby-forum.com/t/class-tree-variables/84959/3 "2007-02-08T21:51:13Z")

</div>

On Feb 8, 12:41 pm, removed\_email\_address@domain.invalid wrote:

> > by the rest of the tree.  
> > I think that’s a typo; I don’t see any class variables in your code.

Yes, sorry. I meant “class instance variables” (and also  
“descendants”) but the  
word “instance” got lost in careless editing.

---

<div class="post-metadata">

**Author:** ![oinkoink](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/o/8e8cbc/32.png) [@oinkoink](https://www.ruby-forum.com/u/oinkoink)\
**Post date:** [February 8, 2007, 10:14pm UTC](https://www.ruby-forum.com/t/class-tree-variables/84959/4 "2007-02-08T22:14:14Z")

</div>

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 W.

---

<div class="post-metadata">

**Author:** ![oinkoink](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/o/8e8cbc/32.png) [@oinkoink](https://www.ruby-forum.com/u/oinkoink)\
**Post date:** [February 8, 2007, 10:34pm UTC](https://www.ruby-forum.com/t/class-tree-variables/84959/5 "2007-02-08T22:34:17Z")

</div>

Hi –

On Fri, 9 Feb 2007, Gary W. wrote:

> 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 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.

> in Ruby than in other languages because of 1) and 2)

1. 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.

> @@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

---

<div class="post-metadata">

**Author:** ![oinkoink](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/o/8e8cbc/32.png) [@oinkoink](https://www.ruby-forum.com/u/oinkoink)\
**Post date:** [February 8, 2007, 11:33pm UTC](https://www.ruby-forum.com/t/class-tree-variables/84959/6 "2007-02-08T23:33:23Z")

</div>

On Feb 8, 2007, at 4:33 PM, removed\_email\_address@domain.invalid wrote:

> I think there’s an error here; C and D aren’t related to A and B.

My bad, pay attention to the code, not the comments. Comments should  
have had D for B and C for A.

> ```
> p @@alpha
> 
> ```
> 
> end  
> you’ll also get 52.

@@alpha has already been established in Object, which  
takes precedence over anything in String (since it was  
defined first). Consider:

irb(main):001:0\> class A; end  
=\> nil  
irb(main):002:0\> class B  
irb(main):003:1\> def A.foo  
irb(main):004:2\> @@alpha  
irb(main):005:2\> end  
irb(main):006:1\> @@alpha = ‘B scope’  
irb(main):007:1\> end  
=\> “B scope”  
irb(main):008:0\> A.foo  
=\> “B scope”

In this example the definition of A::foo is lexically within the  
(class B;end) block and so @@alpha is resolved relative to B. Not to  
the top-level or relative to B’s singleton class.

> Also, if you do:
> 
> class \<\< A  
> @@alpha = 1  
> end
> 
> p @@alpha
> 
> Object’s @@alpha will be 1.

Well it turns out that the scope created by “class \<\<A; end” is not  
at all like the scope created by “class A; end”, at least with respect  
to class variables. Throw away all the stuff above and consider fresh:

class A  
@@alpha = 1  
end

p (class \<\<A; @@alpha; end) # warning, top-level scope for @@alpha

In fact, I couldn’t figure out how to even create a class variable  
that was anchored to the singleton class of a class. I didn’t try too  
hard though…

Gary W.

---

<div class="post-metadata">

**Author:** ![oinkoink](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/o/8e8cbc/32.png) [@oinkoink](https://www.ruby-forum.com/u/oinkoink)\
**Post date:** [February 8, 2007, 10:51pm UTC](https://www.ruby-forum.com/t/class-tree-variables/84959/7 "2007-02-08T22:51:19Z")

</div>

oinkoink wrote:

> implementation occurs only in the top (root) class and is inherited by  
> the rest of the tree.  
> …

This is a solution to a slightly different problem (inheritance of  
hashes of attributes), but it might be interesting anyway:

[http://redshift.sourceforge.net/superhash/](http://redshift.sourceforge.net/superhash/)

A little example:

require ‘superhash’

class A  
class\_superhash :options

options[:foo] = “A foo”  
options[:bar] = “A bar”

def options; self.class.options; end  
end

class B \< A  
options[:foo] = “B foo”  
end

p A.options  
p B.options.to\_hash  
p B.new.options.to\_hash

**END**

output:

{:foo=\>“A foo”, :bar=\>“A bar”}  
{:foo=\>“B foo”, :bar=\>“A bar”}  
{:foo=\>“B foo”, :bar=\>“A bar”}
