Class instance variables are generally more useful and less surprising than class variables, so you should probably use them.
And now I shall spell some things out in the excruciating detail you've come to expect from a Ruby answer on StackOverflow:
To declare or refer to a class instance variable, you need to be in class scope and use a single @ sign. This places the variable on the singleton class instance for that class.
Unfortunately, when you're in class scope and use the def
keyword, your methods are placed on the list of instance methods for that class, and are executed in instance scope, so their @-sign variables will be on the instance they're in.
What we want instead is to define methods on the class, not on its instances. What that really means is that these methods are on the list of instance methods for the singleton class of the class object. (Phew!)
So, to sum up: There are at least four idioms for switching over and defining methods on the singleton class of the class object Foo
:
class Foo
@a, @b, @c, @d = 1, 2, 3, 4
# 1. pass the target to def
def Foo.a
@a
end
# 2. pass the target to def, relying on the fact that self
# happens to be the class object right now
def self.b
@b
end
# switch from class scope to singleton class scope
class << self
# 3. define a plain accessor in singleton class scope
def c
@c
end
# 4. use a macro to define an accessor
attr_reader :d
end
end
p [Foo.a, Foo.b, Foo.c, Foo.d]
#=> [1, 2, 3, 4]
(There are probably half a dozen more ways to do this, once you factor in class_eval
and define_method
and the like, but that should satisfy you for now. :-))
One final note: class instance variables are only available via the class they're defined on. If you try to call any of those methods from (or via) a subclass, the methods will execute, but the @ variables will all be nil, since self
will be the subclass's class object, not the parent class' class object.
class Bar < Foo
end
p [Bar.a, Bar.b, Bar.c, Bar.d]
#=> [nil, nil, nil, nil]