Ruby Ruby class variable 求教

ibachue · 2013年04月23日 · 最后由 fbsender 回复于 2013年12月04日 · 5341 次阅读

Hi, all 在做一个关于 Ruby class variable 的实验, 碰到一点问题,求教各位:

class A
  @@a = 1
  def f
    @@a
  end

  def f=(v)
    @@a = v
  end
end

A.new.f #=> 1
A.new.f = 2
A.new.f #=> 2

class A
  def self.f1
    @@a
  end

  class << self
    def f2
      @@a
    end
  end
end

A.f1 #=> 2
A.f2 #=> 2

# 直到这里,所有内容都可以理解
class << A
  def f3
    @@a
  end
end

A.f3 
#=> warning: class variable access from toplevel
#=> NameError: uninitialized class variable @@a in Object

难道用 class << A; ... ;endclass A; class << self; ... ; end; end 有什么区别吗?为啥用后者可以取到 A 的 class variable 但是有前者却会出错?谢谢

class var 各种坑尽量别用...

#1 楼 @luikore 发现了。。。 http://www.oreillynet.com/ruby/blog/2007/01/nubygems_dont_use_class_variab_1.html 虽然是 2007 年的文章了 但是似乎到了 2013 年还是不改进。。

#2 楼 @iBachue 今年要是能把 class variable 删掉就是最大的改进了...

#3 楼 @luikore 👍 确实没啥用 反正和类对象自身的 instance variable 不通用。。。

让我想起声明类的静态方法有三种方式。。。,虽然效果都一样但是都有小区别

应该和 class 关键字的位置有关。

class << A def f3 @@a end end 这种情况会不会是因为匿名类的原因,相当于你重新又在一个类(匿名类)中定义了一个类变量,所以需要重新初始化下

顶层似乎是 Object 类的地盘,参考那个错误信息。因为容易错,才有的那个警告。

/lib/mytest.rb:16: warning: class variable access from toplevel singleton method /lib/mytest.rb:16:in `f3': uninitialized class variable @@a in Object (NameError) from E:/lib/mytest.rb:20

刚在本地执行了下,这个信息要详细点,

已经非常详细了。。。。

这似乎是一个关于“作用域门”的问题。ruby 会在三个地方关闭前一个作用域,同时打开一个新的作用域:类定义、模块定义、方法。 当把 class << self 写在 class A 里面时,此时 ruby 关闭了 Object 的作用域门,打开了 class A 的作用域门,由于 A 里面定义了@@a,所以不会报错。如果把 class << self 写在 class A 外面,则此时上下文为 Object,而 Object 中没有定义@@a,所以会报错。换句话说:class << self 并不是作用域门。

#11 楼 @baxiaopeng 额 貌似是这样的 不过为啥 class << self 就不是 scope gate 呢?

#11 楼 @baxiaopeng 恰恰相反,class << self 是作用域门,但是类变量跟作用域门无关,但是和 level 门有关,class << self 不是 level 门。

#10 楼 @tumayun 参考帖子 http://ruby-china.org/topics/14384 class << self 改变了当前作用域,未改变类变量所属的类,即此时@@a 的所属的类仍被认定为 Object level gate 相关

需要 登录 后方可回复, 如果你还没有账号请 注册新账号