-
-
Save sumanmukherjee03/3915546 to your computer and use it in GitHub Desktop.
# Execute this file as follows and compare the results in ruby 1.8.*: | |
# | |
# ruby class_var_ex.rb | |
# ruby class_var_ex.rb "include module" | |
# ruby class_var_ex.rb "include module" "include global" | |
# ruby "include global" | |
@@test = 9 if ARGV.last == "include global" | |
module X | |
@@test = 3 | |
self.instance_variable_set('@test', 4) | |
def get_class_variable_from_module | |
puts "Class variable from module = " + @@test.to_s | |
end | |
def get_class_instance_variable_from_module | |
puts "Class instance variable from module = " + @test.to_s | |
end | |
end | |
class A | |
extend X | |
@@test = 1 | |
self.instance_variable_set('@test', 2) | |
def self.get_class_variable | |
puts "Class variable = " + @@test.to_s | |
end | |
def self.get_class_instance_variable | |
puts "Class instance variable = " + @test.to_s | |
end | |
end | |
class B < A | |
B.send(:include, X) if ARGV.first == "include module" | |
@@test = 2 | |
self.instance_variable_set('@test', 1) | |
end | |
def extended_modules_class_variable | |
puts "Module's class variable = " + X.send(:class_variable_get, '@@test').to_s | |
end | |
def extended_modules_class_instance_variable | |
puts "Module's class instance variable = " + X.instance_variable_get('@test').to_s | |
end | |
puts "Values from A >>>>>>>>>>>>>>" | |
A.get_class_variable_from_module | |
A.get_class_instance_variable_from_module | |
A.get_class_variable | |
A.get_class_instance_variable | |
puts "Values from B >>>>>>>>>>>>>>" | |
B.get_class_variable_from_module | |
B.get_class_instance_variable_from_module | |
B.get_class_variable | |
B.get_class_instance_variable | |
puts "Values from X >>>>>>>>>>>>>>" | |
extended_modules_class_variable | |
extended_modules_class_instance_variable | |
if ARGV.last == "include global" | |
puts "Values from Global scope >>>>>>>>>>>>>>" | |
puts "Class variable = " + @@test.to_s | |
end |
@mekong, the behavior of the instance variables are totally expected. I punched them in there during the talk just to show the difference and create some context. However, i think the behavior has been resolved. The example i posted does not help answer the questions because i kept the variable names the same. Changing them opened up things.
In case of the class variables, the scope of the class variable in a child is the same as it's parent. So, changing the class variable of a child changes it's parent's class variable too and that behavior is retained through out. So, there is nothing confusing :-) .
I will post 2 more code samples to depict this.
When the module gets included, and the class variable @@test1 is redefined after the inclusion, module X becomes the immediate ancestor of the class B for look up and the class variable being changed in B points to the one initialized in the module X. The scope of that class variable is different than the scope of the class variable of the superclass A, because the superclass of X is not A. Here's the code sample depicting this.
module X
@@test1 = 3
end
class A
@@test1 = 9
def self.get_class_variable
puts "Class variable = " + @@test1.to_s
end
end
class B < A
include X
@@test1 = 2
def self.get_class_variable_from_module
puts "Class variable from module = " + @@test1.to_s
end
end
puts "Values from A >>>>>>>>>>>>>>"
A.get_class_variable
puts "Values from B >>>>>>>>>>>>>>"
B.get_class_variable_from_module
B.get_class_variable
When the module gets included, but the class variable @@test1 is redefined before the inclusion, the class variable being changed in B points to the one initialized in the class A. Here's the code sample depicting this.
class B < A
@@test1 = 2
include X
def self.get_class_variable_from_module
puts "Class variable from module = " + @@test1.to_s
end
end
Continuing from the previous example, when you redefine the class variable again, after the inclusion, the pointer for the class variable changes to the one initialized in module X. So, both class A's class variable and the module X's class variable get changed. Here's the code depicting this.
class B < A
@@test1 = 2
include X
@@test1 = 0
def self.get_class_variable_from_module
puts "Class variable from module = " + @@test1.to_s
end
end
Here's another thing you can do:
Those 2
@@test
's are not the same. The first one overrides the class variable of A by inheritance. The second one overrides the class variable of the module, by virtue of the include. So it looks like include is changing the scope.