下面是我的测试程序:
module Foo
@@bar1 = "1" # static property of the module?
class << self # open static section
@bar2 = "2" # property in static section, should be static property?
def func1 # static function
puts "bar1: #{@@bar1}"
puts "bar2: #{@bar2}"
end
end
end
Foo.func1
生成输出:
$ ruby test.rb
bar1: 1
bar2:
我的问题是,bar1
和bar2
的声明有什么不同?
我认为
- 将
@@
添加到bar1
使其成为静态/类变量(另外,您不能有模块的实例,可以吗?) - 将
bar2
放入class << self
块中也使其成为静态/类变量。
但是,当它们在func1
中打印出来时,bar2
没有初始化。为什么他们的行为不同?
首先,让我们暂时忘记单例类(class << self
)。
模块/类变量(静态变量)与模块/类实例变量不同,如
模块/类变量可以从模块/类和它的实例中访问,但是模块/类实例变量不能。
class X
@@foo = 'foo' # a class variable
@bar = 'bar' # a class instance variable
def self.foo
@@foo
end
def self.bar
@bar
end
def foo
@@foo
end
def bar
@bar
end
end
X.foo #=> "foo"
X.bar #=> "bar"
X.new.foo #=> "foo"
X.new.bar #=> nil
模块/类变量在继承树中是共享的,但是模块/类实例变量不是。
class Parent
@@foo = 'foo in parent'
@bar = 'bar in parent'
def self.foo
@@foo
end
def self.bar
@bar
end
end
class Child < Parent
@@foo = 'foo in child'
@bar = 'bar in child'
end
Parent.foo #=> "foo in child"
Parent.bar #=> "bar in parent"
因此,不建议使用模块/类变量。
让我们多讨论一下模块/类实例变量的行为。
在Ruby中,模块和类都是对象,所以它们可以像普通对象一样拥有自己的实例变量。这些模块/类中的实例变量被称为模块/类实例变量。
在Ruby中,实例变量属于ONLY宿主对象。没有其他对象可以看到它(至少不使用元编程技巧)。类和类的实例是两个不同的对象,所以实例不能访问类的实例变量。一个类和它的子类是两个不同的对象,所以它们不能访问彼此的类实例变量。
最后,我们来谈谈单例类。
每个对象都有自己的单例类。这个单例类只有一个实例——对象。
模块和类都是对象,所以它们可以有自己的单例类。
class << self
打开self
的单例类,在您的代码中,它是模块Foo
。
注意一个模块/类和它的单例类是两个不同的对象,所以它们不共享模块/类的实例变量。模块/类不继承单例类,单例类也不继承模块/类,所以它们也不共享模块/类的变量。