From: Gary Wright Date: 2007-12-17T05:07:35+09:00 Subject: Re: Mixins and class variables On Dec 16, 2007, at 10:25 AM, Brubix wrote: > I can't figure out how to set class variables from class methods > inherited from a module ? > > The following doesn't work as I expected (I spare you my others > pathetic attempts): > > module MyModule > def self.extended(base) > base.setClassVar(base.name.downcase) > end > def setClassVar(value) > puts "self is #{self.name}" > puts "@@classVar=#{value}" > @@classVar = value > end > def getClassVar > @@classVar > end > end > > class Class1 > extend MyModule > end > class Class2 > extend MyModule > end > > puts "classVar for Class1 is " + Class1.getClassVar > puts "classVar for Class2 is " + Class2.getClassVar > > It gives: > self is Class1 > @@classVar=class1 > self is Class2 > @@classVar=class2 > classVar for Class1 is class2 # Shouldn't be class1 ?! > classVar for Class2 is class2 The New Haven Ruby Brigade spent an hour or so one night trying to figure out the scoping rules for class variables. The key to understanding them is to realize that instance variables are dynamical scoped relative to self while class variables are *lexically* scoped (i.e. the scoping is defined by the syntactic structure of the code). In your example, '@@classvar' is lexically located within MyModule. That means it will *always* be associated with MyModule regardless of the value of self at the time setClassVar or getClassVar are executed. Here is another situation that illustrates this difference: class A @@cvar = 'class A' def cvar @@cvar end end puts A.new.cvar # => class A puts A.class_eval { @@cvar } # => NameError, @@cvar undefined The class_eval version fails because @@cvar in the block is not lexically within the class A/end block. It is *dynamically* in the scope of class A, but not lexically within the scope of class A. In this case, @@cvar is resolved to the top-level scope which is associated with Object. MonkeeSage's suggestion to use Module#class_variable_get/set forces the variables to be resolved relative to the receiver and thus bypasses the lexical scoping rules for class variables. This is another situation where the syntactic similarity of the instance variable sigil ("@") and the class variable sigil ("@@") causes people to think they behave in the same manner. They don't. Gary Wright