Hi --

On Sun, 30 Nov 2003, Carl Youngblood wrote:

> > (Just as a footnote, you can also use "normal" accessor shortcuts at
> > the class object level:
> > 
> >   class A
> >     class << self
> >       attr_accessor :x
> >     end
> >   end
> > 
> >   A.x = 1   # and so on
> > 
> > which is implemented with instance variables rather than class
> > variables, if for any reason that suits your purposes better.)
> 
> I'm still trying to figure out what this does, exactly.  Is A.x an 
> instance variable or a class variable?  If I have something like:
> 
> a = A.new
> 
> And I say:
> 
> a.x = 1
> 
> Is that modifying a class variable or an instance variable?  Or does 
> that even work?  I just want to make sure that the accessor will work if 
> called on either an instance or on the class itself.

My example creates an instance variable... but the "instance" is the
Class object, A.  It's a case where one takes advantage of the
"classes are themselves objects" axiom.  I'm creating private state
for the Class object itself.  You could say that, at that moment, A is
wearing its "Object" hat, rather than its "Class" hat.  It doesn't
"know" that it is a Class, or can create instances; it just knows that
it's an Object, and is therefore entitled to have instance variables
just like any other Object.  

So, as with any other object, you can use those accessor methods to
maintain state:

  A.x = 1
  puts A.x   # 1

etc.  

And when you do create instances of A, those instances are separate
objects and have no automatic access to the instance variables of A.
By definition, two objects cannot directly share an instance
variable.  The fact that one object is a Class and the other is an
instance of that class doesn't change this; each is still an object,
with the right to either expose or not expose their instance
variables.  

So if you want a class and its instances to share state, you have to
use a class variable (as in the Ruby Way example), or set up a
situation where the instances have access to the class's own private
state:

  class A
    class << self
      attr_accessor :x
    end

    def x
      self.class.x
    end

    def x=(y)
      self.class.x=(y)
    end
  end

  A.x = 1
  puts A.new.x     # 1

But remember, if you do that, every instance of A will access the
*same* variables:

  a = A.new
  b = A.new
  a.x = 2
  puts b.x    # 2

since #x and #x= are just wrappers for access to another object's
instance variable @x (that other object being the Class object A).  
So that's probably not a great idea in most cases.  Class variables
have their own quirks, though they're scheduled to be a bit de-quirked
in 2.0.


David

-- 
David A. Black
dblack / wobblini.net