在<<中初始化实例变量自我阻止

时间:2014-08-18 20:59:48

标签: ruby

具体来说,为什么以下代码输出nil而不是1

class Foo
  class << self
    @bar = 1
    def bar
      @bar
    end
  end
end
p Foo.bar

3 个答案:

答案 0 :(得分:1)

<< self区块中,self#<Class:Foo>的一个实例。

class Foo
  puts "self in Foo declaration is: #{self} #{self.class} #{self.object_id}"
  class << self 
    @bar = 1
    puts "self in Foo.self declaration is: #{self} #{self.class} #{self.object_id}"
    def bar
      puts "self in class method is #{self} #{self.class} #{self.object_id}"
      @bar
    end
  end
end
p Foo.bar

此代码输出:

self in Foo declaration is: Foo Class 69910818825400
self in Foo.self declaration is: #<Class:Foo> Class 69910818825380
self in class method is Foo Class 69910818825400

因此,对您的代码稍作修改即可按预期运行:

class Foo @bar = 1 class << self def bar @bar end end end p Foo.bar

答案 1 :(得分:0)

即使您正在使用self修改Foo的Class定义,您仍然会设置一个实例变量,该变量在类范围内不可用。

如果你想要一个类变量,就像它一样。

class Foo
  class << self
    @@bar = 1
    def bar
     @@bar
    end
  end
end
p Foo.bar # 1

答案 2 :(得分:0)

这与以下内容完全不同:

class Foo
  @bar = 1

  def bar; @bar end
end

实例变量属于对象,并始终在self上查找。 bar是一种实例方法,因此@bar内的bar属于Foo的某个实例(selfbar的接收者点)。开头的@bar属于类本身(此时selfFoo)。

这些只是两个完全不同的对象。两个'@bar`s完全不相关。

你的示例中:第一个@bar属于Foo的单例类,第二个@bar属于单个类Foo的实例{1}}(即Foo)。

以下是如何使其发挥作用:

class Foo
  @bar = 1

  def self.bar; @bar end
end