[lnkForumImage]
TotalShareware - Download Free Software

Confronta i prezzi di migliaia di prodotti.
Asp Forum
 Home | Login | Register | Search 


 

Forums >

comp.lang.ruby

Popularity Contest: Initializing Class-Level Instance Variables

Gavin Kistner

10/26/2006 4:48:00 AM

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

4 Answers

Ara.T.Howard

10/26/2006 5:34:00 AM

0

Joel VanderWerf

10/26/2006 5:39:00 AM

0

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

--
vjoel : Joel VanderWerf : path berkeley edu : 510 665 3407

Joel VanderWerf

10/26/2006 5:49:00 AM

0

Joel VanderWerf wrote:
> 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:

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]

--
vjoel : Joel VanderWerf : path berkeley edu : 510 665 3407

Trans

10/26/2006 12:06:00 PM

0


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

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.