Created
October 19, 2012 00:17
-
-
Save sumanmukherjee03/3915546 to your computer and use it in GitHub Desktop.
Messing with class variables in ruby
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# 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 |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
@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.
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.
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.