使用class_variable_get
,但前提是必须
class_variable_get
是更好的方法,除了它对你没有“吸引力”。如果你正在进入一个类并打破封装,也许有这个额外的障碍来表明你做错了什么是合适的。
为要访问的变量创建访问器方法
如果这些是您的类,并且访问变量不会破坏封装,那么您应该为它们创建类访问器方法以使其更容易和更漂亮:
class Foo
def self.bar
@@bar
end
end
p Foo.bar
但是,如果这是您的类,您确定需要类变量吗?如果您不理解其中的含义(见下文),您实际上可能想要类本身的实例变量:
class Foo
class << self
attr_accessor :bar
end
end
Foo.bar = 42
p Foo.bar
类变量的行为
类变量对新手来说似乎是在类级别存储信息的正确方法,主要是因为名称。它们也很方便,因为无论您是在类的方法中还是在实例方法中,您都可以使用相同的语法来读取和写入它们。但是,类变量在类及其所有子类之间共享。
例如,考虑以下代码:
class Rectangle
def self.instances
@@instances ||= []
end
def initialize
(@@instances ||= []) << self
end
end
class Square < Rectangle
def initialize
super
end
end
2.times{ Rectangle.new }
p Rectangle.instances
#=> [#<Rectangle:0x25c7808>, #<Rectangle:0x25c77d8>]
Square.new
p Square.instances
#=> [#<Rectangle:0x25c7808>, #<Rectangle:0x25c77d8>, #<Square:0x25c76d0>]
确认!矩形不是正方形!这是做同样事情的更好方法:
class Rectangle
def self.instances
@instances ||= []
end
def initialize
self.class.instances << self
end
end
class Square < Rectangle
def initialize
super
end
end
2.times{ Rectangle.new }
p Rectangle.instances
#=> [#<Rectangle:0x25c7808>, #<Rectangle:0x25c77d8>]
2.times{ Square.new }
p Square.instances
#=> [#<Square:0x25c76d0>, #<Square:0x25c76b8>]
通过在类本身上创建一个实例变量和访问方法——它恰好是Class
类的一个实例,类似于——类的MyClass = Class.new
所有实例(和外部人员)都有一个公共的、干净的位置来读/写不共享的信息其他类之间。
请注意,显式跟踪创建的每个实例将防止对“未使用”实例进行垃圾收集。小心使用上述代码。
以class_eval
更清洁的方式使用
最后,如果您要使用class_eval
,请注意它还有一个块形式,无需解析和 lex 字符串来评估它:
Foo.class_eval('@@bar') # ugh
Foo.class_eval{ @@bar } # yum