see the below code:
class A
end
@class = eval("A")
@class.class_eval do
@@attr = 100
def self.get_attr
@@attr
end
def self.set_attr(_x)
p "hi"
@@attr = _x
end
end
class B
end
@class = eval("B")
@class.class_eval do
@@attr = 100
def self.get_attr
@@attr
end
def self.set_attr(_x)
p "hi"
@@attr = _x
end
end
a = A.new
b = B.new
A.set_attr(103)
B.set_attr(222)
p A.class_variable_defined?(:@@attr)
p B.class_variable_defined?(:@@attr)
p Object.class_variable_defined?(:@@attr)
p A.class_variable_get(:@@attr)
p B.class_variable_get(:@@attr)
p Object.class_variable_get(:@@attr)
p A.class_variables
p B.class_variables
Object.remove_class_variable(:@@attr)
p A.class_variables
p B.class_variables
Output:
true
true
true
222
222
222
[:@@attr]
[:@@attr]
[]
[]
Explanation: As per your code @@attr
belongs to Object
class class variables. And as per Ruby
A and B both are subclass of Object
. Thus the class variables @@attr
has been shared.
Module#class_eval
says:
(a) This can be used to add methods to a class.
(b) when a block is given, constant/class variable look-up is not affected.
This is the feature of ruby that if you use class variable
inside class_eval
it searches that class variable
in the class Object
.
To make it visible I write the below code, which in turn will prove that: constant/class variable look-up is not affected.
@@avar = 1
class A < BasicObject
@@avar = "hello"
end
A.class_eval { puts @@avar }
Look at the code output:
D:/Rubyscript/My ruby learning days/Scripts/TEST.RB:91: warning: class variable
access from toplevel
D:/Rubyscript/My ruby learning days/Scripts/TEST.RB:95: warning: class variable
access from toplevel
1