What is really a class instance variable compare to a class variable?

Hi all,
   
  Given the following definition :
   
  class A
    @@class_var = "a class variable"
    @class_instance_var = "a class instance variable"
   
    def a_method
       @instance_var = "an instance variable"
    end
  end
   
  I understand what is a class variable and what is an instance variable. The problem I have is what is a class instance variable like @class_instance_var ? Where does this variable live ?
   
  A class variable is shared by all instances of the class. But what about the class instance variable ?
   
  Thanks for any explanation.
   
  CM.

···

---------------------------------
The fish are biting.
Get more visitors on your site using Yahoo! Search Marketing.

HI --

Hi all,

Given the following definition :

class A
   @@class_var = "a class variable"
   @class_instance_var = "a class instance variable"

   def a_method
      @instance_var = "an instance variable"
   end
end

I understand what is a class variable and what is an instance
variable. The problem I have is what is a class instance variable
like @class_instance_var ? Where does this variable live ?

A class variable is shared by all instances of the class. But what
about the class instance variable ?

Every instance variable you ever see belongs to whatever object is, at
the moment you see the instance variable, playing the role of 'self'.
Inside a class definition block, 'self' is the class object itself:

   class A
     p self # A
   end

So if you have an instance variable at that point in execution:

   class A
     @x = 1
   end

it belongs to the object A, which is a class object.

Similarly, that variable @x will only be visible when self is A. When
self is not A, @x will not be that same instance variable. You can
always establish ownership of instance variables by calculating what
self is at the point that the instance variable appears.

Keep in mind, too, that the phrase "class instance variable" is just a
way of clarifying that you don't mean "instance variable defined in
this class's instance methods". There's no separate "class instance
variable" construct at the language level; there are just objects,
some of which are class objects and all of which can be self and
therefore have instance variables.

David

···

On Fri, 9 Feb 2007, Ruby Admirer wrote:

--
Q. What is THE Ruby book for Rails developers?
A. RUBY FOR RAILS by David A. Black (http://www.manning.com/black\)
    (See what readers are saying! http://www.rubypal.com/r4rrevs.pdf\)
Q. Where can I get Ruby/Rails on-site training, consulting, coaching?
A. Ruby Power and Light, LLC (http://www.rubypal.com)

David,
   
  Thanks a lot for your reply. But this raises another understanding problem for me. It seems that regarding inheritance there are different behaviours for :
  - an object instance variable
  - a class variable
  - a class instance variable
   
  For the following code (I'm running Ruby 1.8.5p12) :
   
  class TestObject
    def initialize
    @var = "an object instance variable"
  end
    def print
    puts @var
  end
  end
  class DerivedTestObject < TestObject
    def set_var
    @var = "an object instance variable : changed"
  end
  end
  
o = DerivedTestObject.new
o.print
o.set_var
o.print
   
  The output is :
an object instance variable
an object instance variable : changed
   
  => So, an object instance variable is shared/seen by the derived object instances.
   
  For the following code :
   
  class TestClass
    @@var = "a class variable"
  @var = "a class instance variable"
    def self.print
    puts @@var
    puts @var
  end
  end
  class DerivedTestClass < TestClass
    def self.set_var
    @@var = "a class variable : changed"
    @var = "a class instance variable : changed"
  end
  end
  TestClass.print
puts "-------------"
  DerivedTestClass.print
puts "-------------"
  DerivedTestClass.set_var
DerivedTestClass.print
puts "-------------"
  TestClass.print

  The output is :
a class variable
a class instance variable

···

-------------
a class variable
nil
-------------
a class variable : changed
a class instance variable : changed
-------------
a class variable : changed
a class instance variable
   
  => So, a class variable is shared/seen by derived classes (similar behaviour as an instance variable). Conversely, a class instance variable is not shared/seen by derived classes.
   
  Am I missing something ?
   
  Another question :
  The inheritance of a class variable and a class method is really great :-).
  Is it going to be removed in Ruby 2.0 ? I heard something about that but I hope not.
   
  Thanks for any explanation.
   
  CM.
  
dblack@wobblini.net wrote:
  HI --

On Fri, 9 Feb 2007, Ruby Admirer wrote:

Hi all,

Given the following definition :

class A
@@class_var = "a class variable"
@class_instance_var = "a class instance variable"

def a_method
@instance_var = "an instance variable"
end
end

I understand what is a class variable and what is an instance
variable. The problem I have is what is a class instance variable
like @class_instance_var ? Where does this variable live ?

A class variable is shared by all instances of the class. But what
about the class instance variable ?

Every instance variable you ever see belongs to whatever object is, at
the moment you see the instance variable, playing the role of 'self'.
Inside a class definition block, 'self' is the class object itself:

class A
p self # A
end

So if you have an instance variable at that point in execution:

class A
@x = 1
end

it belongs to the object A, which is a class object.

Similarly, that variable @x will only be visible when self is A. When
self is not A, @x will not be that same instance variable. You can
always establish ownership of instance variables by calculating what
self is at the point that the instance variable appears.

Keep in mind, too, that the phrase "class instance variable" is just a
way of clarifying that you don't mean "instance variable defined in
this class's instance methods". There's no separate "class instance
variable" construct at the language level; there are just objects,
some of which are class objects and all of which can be self and
therefore have instance variables.

David

--
Q. What is THE Ruby book for Rails developers?
A. RUBY FOR RAILS by David A. Black (http://www.manning.com/black\)
(See what readers are saying! http://www.rubypal.com/r4rrevs.pdf\)
Q. Where can I get Ruby/Rails on-site training, consulting, coaching?
A. Ruby Power and Light, LLC (http://www.rubypal.com)

---------------------------------
Check out the all-new Yahoo! Mail beta - Fire up a more powerful email and get things done faster.

My understanding is:

(1) An instance variable is only visible to that object. It doesn't matter
what "class" the object is. It's not visible by any other objects, either of
the same class or a different class.

(2) A class instance variable is an instance variable of an object which
happens to be a class (its an object whose class is "Class"). This is also
private to that object, i.e. to the class. A subclass is a different object,
so has its own class instance variables.

(3) Class variables, i.e. @@foo, are voodoo. But yes I believe they are
shared by groups of classes in the same ancestry somehow.

B.

···

On Fri, Feb 09, 2007 at 07:48:37PM +0900, Ruby Admirer wrote:

  => So, an object instance variable is shared/seen by the derived object instances.

Hi --

David,

Thanks a lot for your reply. But this raises another understanding problem for me. It seems that regarding inheritance there are different behaviours for :
- an object instance variable
- a class variable
- a class instance variable

You've got two very different things there:

   - instance variables
   - class variables

Instance variables all behave alike. Class variables are completely
different, and unrelated. It's best not to go into it expecting any
similarity.

For the following code (I'm running Ruby 1.8.5p12) :

class TestObject
   def initialize
   @var = "an object instance variable"
end
   def print
   puts @var
end
class DerivedTestObject < TestObject
   def set_var
   @var = "an object instance variable : changed"
end

o = DerivedTestObject.new
o.print
o.set_var
o.print

The output is :
an object instance variable
an object instance variable : changed

=> So, an object instance variable is shared/seen by the derived
object instances.

Not exactly. Every object has its own instance variables, which are
not seen by any other object. Your DerivedTestObject instance
executes the initialize method, and inside that method, its instance
variable @var is initialized. In set_var, that variable is changed.

The fact that initialize is defined in a superclass doesn't mean
anything. When initialize is executed, 'self' is the new
DerivedTestObject instance. So @var, when it appears in that method,
belongs to that instance.

It's better always to think of instance variables in terms of what
object is 'self' at the moment the instance variable appears. An
instance variable has no knowledge of class or inheritance; it only
knows 'self'.

For the following code :

class TestClass
   @@var = "a class variable"
@var = "a class instance variable"
   def self.print
   puts @@var
   puts @var
end
class DerivedTestClass < TestClass
   def self.set_var
   @@var = "a class variable : changed"
   @var = "a class instance variable : changed"
end
TestClass.print
puts "-------------"
DerivedTestClass.print
puts "-------------"
DerivedTestClass.set_var
DerivedTestClass.print
puts "-------------"
TestClass.print

The output is :
a class variable
a class instance variable
-------------
a class variable
nil
-------------
a class variable : changed
a class instance variable : changed
-------------
a class variable : changed
a class instance variable

=> So, a class variable is shared/seen by derived classes (similar
behaviour as an instance variable). Conversely, a class instance
variable is not shared/seen by derived classes.

No instance variable is shared with any other object. TestClass and
DerivedTestClass are two different objects; therefore, they do not
share instance variables. Again, instance variables have no concept
of "class" or "inheritance". They simply adhere to the object in
whose context as 'self' they are created.

Am I missing something ?

Another question :
The inheritance of a class variable and a class method is really great :-).
Is it going to be removed in Ruby 2.0 ? I heard something about
that but I hope not.

My current understanding is that class variables will be visible only
to the class or module they're defined in, including instance methods
of that class or module. I have mixed emotions about this. I would
actually rather see them disappear. My experience over the years is
that they cause more confusion than they're worth, and that in 2.0
they're going to be *almost* like instance variables of class objects
but not quite... and therefore people are still going to wonder what's
going on and why it has to be there. (At least, I will :slight_smile:

David

···

On Fri, 9 Feb 2007, Ruby Admirer wrote:

--
Q. What is THE Ruby book for Rails developers?
A. RUBY FOR RAILS by David A. Black (http://www.manning.com/black\)
    (See what readers are saying! http://www.rubypal.com/r4rrevs.pdf\)
Q. Where can I get Ruby/Rails on-site training, consulting, coaching?
A. Ruby Power and Light, LLC (http://www.rubypal.com)

Brian, David,
   
  Thanks a lot for your replies.
  It's now crystal clear for me.
   
  David,
   
  Your book is excellent !
  May be you can add these additional explanations in a next revision :-)!
   
  CM.

dblack@wobblini.net wrote:
  Hi --

David,

Thanks a lot for your reply. But this raises another understanding problem for me. It seems that regarding inheritance there are different behaviours for :
- an object instance variable
- a class variable
- a class instance variable

You've got two very different things there:

- instance variables
- class variables

Instance variables all behave alike. Class variables are completely
different, and unrelated. It's best not to go into it expecting any
similarity.

For the following code (I'm running Ruby 1.8.5p12) :

class TestObject
def initialize
@var = "an object instance variable"
end
def print
puts @var
end
end
class DerivedTestObject < TestObject
def set_var
@var = "an object instance variable : changed"
end
end

o = DerivedTestObject.new
o.print
o.set_var
o.print

The output is :
an object instance variable
an object instance variable : changed

=> So, an object instance variable is shared/seen by the derived
object instances.

Not exactly. Every object has its own instance variables, which are
not seen by any other object. Your DerivedTestObject instance
executes the initialize method, and inside that method, its instance
variable @var is initialized. In set_var, that variable is changed.

The fact that initialize is defined in a superclass doesn't mean
anything. When initialize is executed, 'self' is the new
DerivedTestObject instance. So @var, when it appears in that method,
belongs to that instance.

It's better always to think of instance variables in terms of what
object is 'self' at the moment the instance variable appears. An
instance variable has no knowledge of class or inheritance; it only
knows 'self'.

For the following code :

class TestClass
@@var = "a class variable"
@var = "a class instance variable"
def self.print
puts @@var
puts @var
end
end
class DerivedTestClass < TestClass
def self.set_var
@@var = "a class variable : changed"
@var = "a class instance variable : changed"
end
end
TestClass.print
puts "-------------"
DerivedTestClass.print
puts "-------------"
DerivedTestClass.set_var
DerivedTestClass.print
puts "-------------"
TestClass.print

The output is :
a class variable
a class instance variable
-------------
a class variable
nil
-------------
a class variable : changed
a class instance variable : changed
-------------
a class variable : changed
a class instance variable

=> So, a class variable is shared/seen by derived classes (similar
behaviour as an instance variable). Conversely, a class instance
variable is not shared/seen by derived classes.

No instance variable is shared with any other object. TestClass and
DerivedTestClass are two different objects; therefore, they do not
share instance variables. Again, instance variables have no concept
of "class" or "inheritance". They simply adhere to the object in
whose context as 'self' they are created.

Am I missing something ?

Another question :
The inheritance of a class variable and a class method is really great :-).
Is it going to be removed in Ruby 2.0 ? I heard something about
that but I hope not.

My current understanding is that class variables will be visible only
to the class or module they're defined in, including instance methods
of that class or module. I have mixed emotions about this. I would
actually rather see them disappear. My experience over the years is
that they cause more confusion than they're worth, and that in 2.0
they're going to be *almost* like instance variables of class objects
but not quite... and therefore people are still going to wonder what's
going on and why it has to be there. (At least, I will :slight_smile:

David

···

On Fri, 9 Feb 2007, Ruby Admirer wrote:

--
Q. What is THE Ruby book for Rails developers?
A. RUBY FOR RAILS by David A. Black (http://www.manning.com/black\)
(See what readers are saying! http://www.rubypal.com/r4rrevs.pdf\)
Q. Where can I get Ruby/Rails on-site training, consulting, coaching?
A. Ruby Power and Light, LLC (http://www.rubypal.com)

---------------------------------
Need a quick answer? Get one in minutes from people who know. Ask your question on Yahoo! Answers.

hi there,

not to hijack the thread or anything, but since it´s about class variables.

i write a lot of rails plugins and i use class variables a lot when
doing mixins that need to have values propagated to the class that is
getting the module mixed in.

like this:

class Foo
end

module Bar
        @@a = "some value"
        A = "some other value"

        def classvar
                return @@a
        end
        def classconst
                return A
        end
end

dup = Foo.new
dup.extend Bar
puts dup.classvar
puts dup.classconst

i find class variables really useful for that. on the other hand like in
my code you could always use class constants which pretty much do the
same in my understanding (please correct me if i´m wrong here)

just wanted to show this as a valid (at least from my perspective) use
case for class variables.

kind regards,

alexander

dblack@wobblini.net wrote:

···

Hi --

On Fri, 9 Feb 2007, Ruby Admirer wrote:

David,

Thanks a lot for your reply. But this raises another understanding
problem for me. It seems that regarding inheritance there are
different behaviours for :
- an object instance variable
- a class variable
- a class instance variable

You've got two very different things there:

  - instance variables
  - class variables

Instance variables all behave alike. Class variables are completely
different, and unrelated. It's best not to go into it expecting any
similarity.

For the following code (I'm running Ruby 1.8.5p12) :

class TestObject
   def initialize
   @var = "an object instance variable"
end
   def print
   puts @var
end
end
class DerivedTestObject < TestObject
   def set_var
   @var = "an object instance variable : changed"
end
end

o = DerivedTestObject.new
o.print
o.set_var
o.print

The output is :
an object instance variable
an object instance variable : changed

=> So, an object instance variable is shared/seen by the derived
object instances.

Not exactly. Every object has its own instance variables, which are
not seen by any other object. Your DerivedTestObject instance
executes the initialize method, and inside that method, its instance
variable @var is initialized. In set_var, that variable is changed.

The fact that initialize is defined in a superclass doesn't mean
anything. When initialize is executed, 'self' is the new
DerivedTestObject instance. So @var, when it appears in that method,
belongs to that instance.

It's better always to think of instance variables in terms of what
object is 'self' at the moment the instance variable appears. An
instance variable has no knowledge of class or inheritance; it only
knows 'self'.

For the following code :

class TestClass
   @@var = "a class variable"
@var = "a class instance variable"
   def self.print
   puts @@var
   puts @var
end
end
class DerivedTestClass < TestClass
   def self.set_var
   @@var = "a class variable : changed"
   @var = "a class instance variable : changed"
end
end
TestClass.print
puts "-------------"
DerivedTestClass.print
puts "-------------"
DerivedTestClass.set_var
DerivedTestClass.print
puts "-------------"
TestClass.print

The output is :
a class variable
a class instance variable
-------------
a class variable
nil
-------------
a class variable : changed
a class instance variable : changed
-------------
a class variable : changed
a class instance variable

=> So, a class variable is shared/seen by derived classes (similar
behaviour as an instance variable). Conversely, a class instance
variable is not shared/seen by derived classes.

No instance variable is shared with any other object. TestClass and
DerivedTestClass are two different objects; therefore, they do not
share instance variables. Again, instance variables have no concept
of "class" or "inheritance". They simply adhere to the object in
whose context as 'self' they are created.

Am I missing something ?

Another question :
The inheritance of a class variable and a class method is really
great :-).
Is it going to be removed in Ruby 2.0 ? I heard something about
that but I hope not.

My current understanding is that class variables will be visible only
to the class or module they're defined in, including instance methods
of that class or module. I have mixed emotions about this. I would
actually rather see them disappear. My experience over the years is
that they cause more confusion than they're worth, and that in 2.0
they're going to be *almost* like instance variables of class objects
but not quite... and therefore people are still going to wonder what's
going on and why it has to be there. (At least, I will :slight_smile:

David