Suppose you had this:
class TestClass
module ClassMethods
attr_accessor :number
def initialize
@number = 47
end
end
include ClassMethods
extend ClassMethods
end
Let's get some information about this class:
TestClass.instance_variables #=> []
No surprise there.
tc = TestClass.new #=> #<TestClass:0x00000101098a10 @number=47>
p tc.instance_variables #=> [:@number]
tc.number #=> 47
tc.number = 11
All as expected. The instance variable @number was created by initialize and we can inspect and change its value with the accessor.
extend made TestClass#initialize a class method, but it has not been invoked. Let's invoke it to initialize the class instance variable @number:
TestClass.initialize
#=> NoMethodError: private method `initialize' called for TestClass:Class
Ah, yes, initializeis a private method.
TestClass.methods.include?(:initialize) #=> false
TestClass.private_methods.include?(:initialize) #=> true
We cannot invoke private class methods in the usual way. send, however, works with private as well as public methods:
TestClass.send :initialize #=> 47
TestClass.instance_variables #=> [:@number]
TestClass.instance_variable_get(:@number) #=> 47
So now the class instance variable has been created set equal to 47. Has it changed the value of the instance variable @number?
tc.number #=> 11
It's not changed. Now let's change the value of the class instance variable and then see if the value of instance variable is affected:
TestClass.instance_variable_set(:@number, -5) #=> -5
tc.number #=> 11
If you'd like to add an accessor for the class instance variable @number, add this line to the class or module:
Module.instance_eval("attr_accessor :number")
(For an explanation, see my answer here.)
Then test:
TestClass.number #=> -5
TestClass.number = 107
TestClass.number #=> 107
TestClass; the second is a class instance variable. They can coexist, as they are as different as@nightand@day.