看了 RubyChina 关于常量的发言,引发了我对常量的兴趣:
#当前类是Object
self.class
#=>Object
#添加一个类C
class C ; end
Object.constants.grep /^C$/
#=>[:C]
#这时在当前类Object中添加了常量 :C
#:所以类名是常量。
类名常量 C 添加在 Object 类中 Object 是所有类的 superclass(BasicObject 除外),所以在所有类中都可见。
如果:
module M
class C; end
end
Object.constants.grep /^M$/
#=>[:M]
Object.constants.grep /^C$/
#=>[]
M.constants
#=>[:C]
#---------关于 Kernel#load 方法的实验----------
#person.rb
#class Person; end
class C
class D
def self.init
load './person.rb'
end
init #load到Object,而不是C::D
end
end
Object.constants.grep /^C$|^Person$/
#=>[:C,:Person]
Object.constants.grep /^D$/
#=>[]
C.constants
#=>[:D]
#类名常量C是指向(reference)类C的对象
class C
def hi
p 'hi, in class C'
end
end
#变量cc
cc = C
cc.name
#=>"C"
cc.new.hi
#=> 'hi, in class C'
#改变常量C,(实验需要,平时不建议改变常量^_^)
C = "i'm string now" #assign
#=>warning.....
#C还是常量
Object.constants.grep /^C$/
#=>[:C]
C
#=>"i'm string now"
#指向了String类的对象。
#变量cc没变,指向类C
cc.name
#=>"C"
cc.new.hi
#=> 'hi, in class C'
#D是常量
D = cc
Object.constants.grep /^C$|^D$/
#=>[:C,:D]
D.name
#=>"C"
#常量D指向类C
#打开类C,添加方法sing
class D # D是指向类C的常量!!!
def sing
'singing'
end
end
#常量D和变量cc共同指向C类
D.instance_methods(false)
cc.instance_methods(false)
#=>[:hi,:sing]
#通过变量cc,向类C 添加方法
cc.send(:define_method, :dance){"dance"}
cc.instance_methods(false)
D.instance_methods(false)
#=>[:hi,:sing,:dance]