Ruby doesn't have class variables in the sense that, say, Java (where they are called static fields) has them. It doesn't need class variables, because classes are also objects, and so they can have instance variables just like any other object.
Class Variables In InheritanceWe can use the parent class or child class name to change the value of a parent class's class variable in the child class. What if both child class and parent class has the same class variable name. In this case, the child class will not inherit the class variable of a base class.
Ruby Class VariablesClass variables begin with @@ and must be initialized before they can be used in method definitions. Referencing an uninitialized class variable produces an error. Class variables are shared among descendants of the class or module in which the class variables are defined.
The Ruby class Class inherits from Module and adds things like instantiation, properties, etc – all things you would normally think a class would have. Because Module is literally an ancestor of Class , this means Modules can be treated like classes in some ways. As mentioned, you can find Module in the array Class.
The @@variables
aren't class variables. They are class hierarchy variables, i.e. they are shared between the entire class hierarchy, including all subclasses and all instances of all subclasses. (It has been suggested that one should think of @@variables
more like $$variables
, because they actually have more in common with $globals
than with @ivars
. That way lies less confusion. Others have gone further and suggest that they should simply be removed from the language.)
Ruby doesn't have class variables in the sense that, say, Java (where they are called static fields) has them. It doesn't need class variables, because classes are also objects, and so they can have instance variables just like any other object. All you have to do is to remove the extraneous @
s. (And you will have to provide an accessor method for the class instance variable.)
class A
def self.init config
@config = config
end
def self.config # This is needed for access from outside
@config
end
def config
self.class.config # this calls the above accessor on self's class
end
end
Let's simplify this a bit, since A.config
is clearly just an attribute_reader:
class A
class << self
def init config
@config = config
end
attr_reader :config
end
def config
self.class.config
end
end
And, in fact, A.init
is just a writer with a funny name, so let's rename it to A.config=
and make it a writer, which in turn means that our pair of methods is now just an accessor pair. (Since we changed the API, the test code has to change as well, obviously.)
class A
class << self
attr_accessor :config
end
def config
self.class.config
end
end
class B < A; end
class C < A; end
B.config = "bar"
p B.new.config # => "bar"
p C.new.config # => nil
C.config = "foo"
p B.new.config # => "bar"
p C.new.config # => "foo"
However, I can't shake the feeling that there is something more fundamentally iffy about the design, if you need this at all.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With