It sometimes makes me wonder why Ruby differentiates between instance
variables and class variables. The latter seem exceptional, for a
number of reasons.
[Ara:]
~/eg/ruby > cat classvar.rb
class A
@@a = 42 # i am a class var, and can be inherited
@a = 42 # i belong to THIS instance of a class, class A
end
class B < A
printf “@@a = <%s>\n”, (@@a or ‘nil’)
printf “@a = <%s>\n”, (@a or ‘nil’)
end
~/eg/ruby > ruby classvar.rb
@@a = <42>
@a =
Yeah, I know the theory (but thanks for summarising anyway), but I haven’t
comfortably fit it in to my programming arsenal. e.g. recently I had some
code like this.
class Project
@@implemented_methods =
def implement(_method)
# some checking
yield
# some checking
@@implemented_methods << _method
end
def Project.implemented_methods
@@implemented_methods
end
end
So, what do I consider “exceptional”? Some comments:
-
Accessing a class variable is nowhere near as convenient as
accessing an instance variable.
-
“class methods” and “instance methods” are the same concept
(since classes are objects), but there’s nothing to unify
“class variables” and “instance variables”. Observe that
a) class variables (@@example) can be resolved whether “self”
represents the class or the instance
b) “class methods”, unlike in Java (static methods), can’t be
directly accessed from the instance
-
Although “class instance variables” are a logical entity,
they do not appear to be a common programming idiom.
I initially tried to code my example like this:
class Project
class << Project
attr_accessor :implemented_methods
end
def implement(_method)
# some checking
yield
# some checking
Project.implemented_methods << _method
end
end
Note in both examples, the idea is to be able to call
Project.implemented_methods
after calling Project#implement a number of times. However, the second
case (using a class instance variable instead of a class variable) did not
work. I think the array always came back empty. Now I may have done
something simple wrong, but I think I’ve demonstrated enough anyway.
Well, I hope so.
Cheers,
Gavin