测试环境是 ruby1.8.7。ruby1.9,ruby2.0 版本不适用 各位看官,请看回复中的用于 ruby1.9 和 2.0 的帖子 NOTE:类变量并不真正属于类,它们属于类体系结构,可以被类或类的实例所使用。(类变量必须被初始化) 场景一:
# 代码a
@@v = 1
class MyClass
@@v
end
代码 a 中,@@v = 1 定义于 main 对象的上下文,因此它属于 main 的类 Object,所以也属于 Object 的所有子类。类 MyClass 继承自 Object,因此也共享了这个类变量
# 代码b
@@v = 1
class MyClass
@@v =2
end
p @@v #=>2
代码 b 中,类 MyClass 修改了共享类变量@@v,因此 Object 中类变量值也被改变了。
# 代码c
class MyClass
@@v
end
@@v = 1
代码 c 中,执行这个文件时,会报没有初始化类变量@@v 的错误,也就是说,在类 MyClass 的祖先链中未发现已定义的@@v,因此在类 MyClass 中开始定义@@v,并且必须被初始化
# 代码d
class MyClass
@@v =2
end
@@v = 1
Object.class_variable_get :@@v #=>1
代码 d 是代码 c 的进化版本,由于在类 MyClass 的祖先链中未发现已定义的@@v,因此在类 MyClass 中定义的@@v = 2 属于该类及所有子类,且可以被该类的实例所使用。 代码 d 中在类下方定义了@@v=1,这里的@@v=1 属于 Object 可以被其子类共享,与 MyClass 中@@v 是两个不同的类变量。Object 中类变量@@v=1 不能被 MyClass 及其子类所共享。 从代码 d 中可以看到,MyClass 中@@v 的改变不会影响 Object 中类变量(因为 MyClass 中类变量不是共享于 Object 的类变量)。也可以通过 MyClass 的子类来验证
# 代码e
@@v = 1
class MyClass
@@v =2
def my_method
p @@v
end
end
MyClass.new.my_method #=> 2
p @@v #=>2
代码 e 中,MyClass 中@@v 是共享于 Object 中类变量(@@v 定义于 Object),因此 MyClass 中@@v 的改变会影响定义于 Object 中@@v 的值
# 代码f
class MyClass
@@v =2
def my_method
p @@v
end
end
@@v = 1
MyClass.new.my_method #=> 2
p @@v #=>1
代码 f 中,MyClass 中@@v=2 与 Object 中@@v=1 是两个不同的类变量,不存在共享的关系,而是分别定义于不同的类中。因此@@v 的改变不会影响彼此
# 代码g
class MyClass
def my_method
p @@v
@@v = 2 #修改共享类变量值
end
end
@@v = 1
MyClass.new.my_method #=> 1
p @@v #=>2
代码 g 中,MyClass 的方法 my_method 中@@v 属于共享的类变量,共享于 Object 中的@@v,因此在 my_method 中修改@@v 的值会影响定义于 Object 中@@v 的值。(定义于方法中的代码,只有在方法调用时才执行)
场景二
# f1.rb
module M1
@@via = "M1"
def self.m1
p @@via
end
end
# f2.rb
module M2
@@via = "M2"
def self.m2
p @@via
end
end
# 图1-1
@@via = "object"
require "f1.rb"
require "f2.rb"
class MyClass
include M1
include M2
def my_method
p @@via
end
end
MyClass.new.my_method #=> "M2"
p @@via #=>"object"
M1.m1 #=> "M1"
M2.m2 #=> "M2"
# 图1-2
@@via = "object"
require "f1.rb"
require "f2.rb"
class MyClass
include M1
include M2
@@via = "myclass"
def my_method
p @@via
end
end
MyClass.new.my_method #=> "myclass"
p @@via #=>"object"
M1.m1 #=> "M1"
M2.m2 #=> "myclass"
图 1-1 和图 1-2 中分别在 M1、M2 和 Object 中定义了@@via,这三个@@via 是三个不同的类变量。Object 中定义的@@via 可以被其子类 MyTest 共享;M1 中定义的@@via 可以被 include 的类共享;M2 中定义的@@via 也可以被 include 的类共享;那么类 MyTest 中共享的@@via 应该是哪个类或模块中定义的@@via? 通过图 1-1 和图 1-2 的例子可以理解为: 类也是按照祖先链的方向来查找定义@@via 的类或模块,修改共享@@via 的值则会影响首次查找到的定义@@via 的类或模块中@@via 的值。 若在类的祖先链上未查找到有定义@@via 的类或模块,则类中显示@@via 的地方所表示的意思为:在此处定义@@via 且必须初始化(非共享的类变量)