变量声明:"@@"和"class << self"之间的差异



下面是我的测试程序:

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:

我的问题是,bar1bar2的声明有什么不同?

我认为

  • @@添加到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

注意一个模块/类和它的单例类是两个不同的对象,所以它们不共享模块/类的实例变量。模块/类不继承单例类,单例类也不继承模块/类,所以它们也不共享模块/类的变量。

相关内容

最新更新