Can anyone tell me about the difference between class variables and class instance variables?
Would be thankful....
Can anyone tell me about the difference between class variables and class instance variables?
Would be thankful....
A class variable (@@) is shared among the class and all of its descendants. A class instance variable (@) is not shared by the class's descendants.
Class variable (@@)
Let's have a class Foo with a class variable @@i, and accessors for reading and writing @@i:
class Foo
@@i = 1
def self.i
@@i
end
def self.i=(value)
@@i = value
end
end
And a derived class:
class Bar < Foo
end
We see that Foo and Bar have the same value for @@i:
p Foo.i # => 1
p Bar.i # => 1
And changing @@i in one changes it in both:
Bar.i = 2
p Foo.i # => 2
p Bar.i # => 2
Class instance variable (@)
Let's make a simple class with a class instance variable @i and accessors for reading and writing @i:
class Foo
@i = 1
def self.i
@i
end
def self.i=(value)
@i = value
end
end
And a derived class:
class Bar < Foo
end
We see that although Bar inherits the accessors for @i, it does not inherit @i itself:
p Foo.i # => 1
p Bar.i # => nil
We can set Bar's @i without affecting Foo's @i:
Bar.i = 2
p Foo.i # => 1
p Bar.i # => 2
First you must understand that classes are instances too -- instances of the Class
class.
Once you understand that, you can understand that a class can have instance variables associated with it just as a regular (read: non-class) object can.
Hello = Class.new
# setting an instance variable on the Hello class
Hello.instance_variable_set(:@var, "good morning!")
# getting an instance variable on the Hello class
Hello.instance_variable_get(:@var) #=> "good morning!"
Note that an instance variable on Hello
is completely unrelated to and distinct from an instance variable on an instance of Hello
hello = Hello.new
# setting an instance variable on an instance of Hello
hello.instance_variable_set(:@var, :"bad evening!")
# getting an instance variable on an instance of Hello
hello.instance_variable_get(:@var) #=> "bad evening!")
# see that it's distinct from @var on Hello
Hello.instance_variable_get(:@var) #=> "good morning!"
A class variable on the other hand is a kind of combination of the above two, as it accessible on Hello
itself and its instances, as well as on subclasses of Hello
and their instances:
HelloChild = Class.new(Hello)
Hello.class_variable_set(:@@class_var, "strange day!")
hello = Hello.new
hello_child = HelloChild.new
Hello.class_variable_get(:@@class_var) #=> "strange day!"
HelloChild.class_variable_get(:@@class_var) #=> "strange day!"
hello.singleton_class.class_variable_get(:@@class_var) #=> "strange day!"
hello_child.singleton_class.class_variable_get(:@@class_Var) #=> "strange day!"
Many people say to avoid class variables
because of the strange behaviour above, and recommend the use of class instance variables
instead.