变量声明:" @@"之间的差异和"类<<自"

时间:2016-07-04 01:37:43

标签: ruby class variables scope static

这是我的测试程序:

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的声明之间有什么区别?

我以为

但是,当它们在func1打印出来时,bar2未初始化。他们为什么表现不同?

1 个答案:

答案 0 :(得分:3)

首先,让我们暂时忘掉单身人士课程(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 到主机对象。没有其他对象可以看到它(至少不使用元编程技巧)。

该类的类和实例是2个不同的对象,因此实例无法访问类实例变量。它的类和子类是2个不同的对象,因此它们不能相互访问类实例变量。

最后,让我们谈谈单身人士课程。

每个对象都有自己的单例类。该单例类只有一个实例 - 对象。

模块和类是对象,因此它们可以有自己的单例类。

class << self打开self的单件类,在您的代码中,它是模块Foo

请注意,模块/类及其单例类是2个不同的对象,因此它们不共享模块/类实例变量。模块/类不继承单例类,单例类也不继承模块/类,因此它们也不共享模块/类变量。