# Popularity Contest: Initializing Class-Level Instance Variab

**URL:** <https://www.ruby-forum.com/t/popularity-contest-initializing-class-level-instance-variab/73679>\
**Category:** Ruby\
**Created:** [October 26, 2006, 6:51am UTC](https://www.ruby-forum.com/t/popularity-contest-initializing-class-level-instance-variab/73679 "2006-10-26T06:51:31Z")\
**Posts on this page:** 5\
**Page:** 1

<div class="post-metadata">

**Author:** ![phrogz](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/p/2acd7d/32.png) [@phrogz](https://www.ruby-forum.com/u/phrogz)\
**Post date:** [October 26, 2006, 6:51am UTC](https://www.ruby-forum.com/t/popularity-contest-initializing-class-level-instance-variab/73679/1 "2006-10-26T06:51:31Z")

</div>

Subclassing a class that uses class-level instance variables requires  
that you initialize them for subclasses. Which of the following three  
techniques do you prefer?

## TECHNIQUE 1 - EXPLICIT INITIALIZATION

class Alpha  
@foo = []  
def self.m1; @foo \<\< rand; end  
def self.m2; @foo.map{ rand }; end  
end

class Bravo \< Alpha  
@foo = []  
end

## TECHNIQUE 2 - ON-DEMAND TEST/INITIALIZATION

class Alpha  
def self.m1; (@foo||=[]) \<\< rand; end  
def self.m2; (@foo||=[]).map{ rand }; end  
end

class Bravo \< Alpha

# Nothing special here

end

## TECHNIQUE 3 - PARENT CLASS HANDLES FOR SUB-CLASSES

class Alpha  
@foo = []  
def self.m1; @foo \<\< rand; end  
def self.m2; @foo.map{ rand }; end  
def self.inherited(subklass)  
subklass.instance\_eval{ @foo=[] }  
end  
end

class Bravo \< Alpha

# Nothing special here

end

---

<div class="post-metadata">

**Author:** ![phrogz](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/p/2acd7d/32.png) [@phrogz](https://www.ruby-forum.com/u/phrogz)\
**Post date:** [October 26, 2006, 7:35am UTC](https://www.ruby-forum.com/t/popularity-contest-initializing-class-level-instance-variab/73679/2 "2006-10-26T07:35:33Z")

</div>

On Thu, 26 Oct 2006, Phrogz wrote:

> Subclassing a class that uses class-level instance variables requires that  
> you initialize them for subclasses. Which of the following three techniques  
> do you prefer?

harp:~ \> cat a.rb  
require ‘rubygems’  
require ‘attributes’

class A  
class \<\< self  
attribute ‘a’ =\> 42  
attribute(:b){ “ **#{ self.name }** ” } # deferred initialization!  
end  
end

class B \< A  
end

p A.a  
p A.b  
p B.a  
p B.b

harp:~ \> ruby a.rb  
42  
“ **A** ”  
42  
“ **B** ”

one can use traits too - but it’s pretty heavy if you don’t need all  
it’s  
features. btw, traits was writtern to solve **exactly** this common  
problem.

regards.

-a

---

<div class="post-metadata">

**Author:** ![phrogz](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/p/2acd7d/32.png) [@phrogz](https://www.ruby-forum.com/u/phrogz)\
**Post date:** [October 26, 2006, 7:49am UTC](https://www.ruby-forum.com/t/popularity-contest-initializing-class-level-instance-variab/73679/3 "2006-10-26T07:49:34Z")

</div>

Joel VanderWerf wrote:

> > end
> 
> I prefer a variant of the above:

Oops, midway through that exercise I forgot we were talking about class  
methods, not instance methods. The following runs correctly:

require ‘set’

class Alpha  
def self.foo  
@foo ||= []  
end  
def self.m1; foo \<\< rand; end  
def self.m2; foo.map{ rand }; end

# note that the expression for contstructing foo is not

# repeated twice

end

class Bravo \< Alpha

# Nothing special here

end

class Charlie \< Alpha  
def self.foo  
@foo ||= Set.new # or some other collection class  
end

# This implies that all _subclasses_ of Charlie will

# (unless overridden) use a set for the #foo method

end

class Delta \< Charlie

# default to Charlie’s choice of Set as the foo collection

end

class Echo \< Alpha  
@foo = [1,2,3] # possible to specify in advance  
end

[Alpha, Bravo, Charlie, Delta, Echo].each {|c| p c.m1}

[0.657784608794096]  
[0.340975041442558]  
#\<Set: {0.191071815451883}\>  
#\<Set: {0.971105015466828}\>  
[1, 2, 3, 0.58602201527139]

---

<div class="post-metadata">

**Author:** ![phrogz](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/p/2acd7d/32.png) [@phrogz](https://www.ruby-forum.com/u/phrogz)\
**Post date:** [October 26, 2006, 2:11pm UTC](https://www.ruby-forum.com/t/popularity-contest-initializing-class-level-instance-variab/73679/4 "2006-10-26T14:11:52Z")

</div>

Phrogz wrote:

> def self.m2; @foo.map{ rand }; end  
> end
> 
> class Bravo \< Alpha  
> @foo = []  
> end

Or:

class Alpha  
@foo = []  
def self.m1; @foo \<\< rand; end  
def self.m2; @foo.map{ rand }; end  
def self.inherited(base)  
base.class\_eval { @foo=[] }  
end  
end

class Bravo \< Alpha  
end

T.

---

<div class="post-metadata">

**Author:** ![phrogz](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/p/2acd7d/32.png) [@phrogz](https://www.ruby-forum.com/u/phrogz)\
**Post date:** [October 26, 2006, 7:39am UTC](https://www.ruby-forum.com/t/popularity-contest-initializing-class-level-instance-variab/73679/5 "2006-10-26T07:39:34Z")

</div>

Phrogz wrote:

> ## TECHNIQUE 2 - ON-DEMAND TEST/INITIALIZATION
> 
> class Alpha  
> def self.m1; (@foo||=[]) \<\< rand; end  
> def self.m2; (@foo||=[]).map{ rand }; end  
> end
> 
> class Bravo \< Alpha
> 
> # Nothing special here
> 
> end

I prefer a variant of the above:

class Alpha  
def foo  
@foo ||= []  
end  
def self.m1; foo \<\< rand; end  
def self.m2; foo.map{ rand }; end

# note that the expression for contstructing foo is not

# repeated twice

end

class Bravo \< Alpha

# Nothing special here

end

class Charlie \< Alpha  
def foo  
@foo ||= Set.new # or some other collection class  
end

# This implies that all _subclasses_ of Charlie will

# (unless overridden) use a set for the #foo method

end

class Delta \< Charlie

# default to Charlie’s choice of Set as the foo collection

end

class Echo \< Alpha  
def initialize(\*)  
super  
@foo = [1,2,3] # possible to specify in advance  
end  
end
