Ruby 对象的单件方法无法访问所属类的类变量,why?

fbsender · 2013年12月04日 · 最后由 sevk 回复于 2013年12月06日 · 3153 次阅读

标题很拗口,一个关于类变量的问题

类变量应该是类、子类、类对象、子类对象共享的

但是类的对象的单件方法却无法访问所属类的类变量...

代码如下,有木有合理的解释呢?

class A
    @@a = "It is @@a"
    def get_a
        @@a
    end
end

obj = A.new

puts obj.get_a                 #=>It is @@a

def obj.test_singleton
    "A test"
end

puts obj.test_singleton    #=>A test

def obj.get_a_singleton
    puts @@a
end

obj.get_a_singleton        #=>in `get_a_singleton': uninitialized class variable @@a in Object (NameError)
def obj.get_a_singleton
    puts @@a
end

这里的@@a 是直接从 main 传递过来的,class 里的@@a 作用域只在类里,出了类只能用方法调用

因为前面的@@a 是 class A 的类变量,class << obj 里面的@@a 是 obj 的 singleton class 里的@@a,加上

obj.singleton_class.class_eval do
    @@a = 1
end

这个@@a 才是 obj.get_a_singleton 能读到的@@a

#3 楼 @piecehealth class_eval 并不会改变当前类变量所属的类

obj.singleton_class.class_eval do
    @@a = 1
end

这里面的@@a 是属于顶层 Object 类的类变量

#4 楼 @fbsender 这里面的@@a是属于顶层Object类的类变量只是现象,不知道是什么原因。

class A
    @@a = "It is @@a"
    def get_a
        puts @@a
    end
end

obj = A.new

obj.get_a

obj.singleton_class.class_eval do
    # 如果这里相当于Object.class_eval的话,为什么下面的get_a_singleton只属于obj?
    @@a = 1

    def get_a_singleton
        puts @@a
    end

end

obj.get_a_singleton

不过 singleton_class 作为一个只有一个实例匿名的类想不出 class variable 能有什么作用,所以从使用的角度来说这种场景应该不会出现。

#5 楼 @piecehealth

class A
    @@a = "It is @@a"
    def get_a
        puts @@a
    end
end

obj = A.new

obj.get_a

obj.singleton_class.class_eval do
    # 如果这里相当于Object.class_eval的话,为什么下面的get_a_singleton只属于obj?
    # get_a_singleton只属于obj木有问题,这里的@@a是属于顶层Object
    @@a = 1

    def get_a_singleton
        puts @@a
    end

end
@@a = 2 

puts obj.get_a_singleton  #=> 2

实际情况会这样用吗?

#7 楼 @sevk 同问,何种情况下使用 class_variable

#8 楼 @fbsender 一般是这样用的:

puts obj.test_singleton    #=>A test

class A
 def get_a_singleton
    puts @@a
 end
end

obj.get_a_singleton  #=>  It is @@a 
需要 登录 后方可回复, 如果你还没有账号请 注册新账号