我个人对此没有任何反对意见,除了它很长,但真正困扰我的是单词eval
。
我用JavaScript做了很多事情,我从任何类似eval的东西运行,就像它是魔鬼一样,我也不喜欢参数是字符串的事实(同样,可能是因为它是eval)。
我知道我可以编写自己的方法来解决方法名称长度问题、我的"方法名称问题"和参数-字符串之类的问题,但我真正想知道的是:是否有更好、更短、更花哨但本机的class_eval
方法来提取类变量
旁注:我知道class_variable_get()
和class_variables()
的存在,但它们看起来并没有真正吸引我;太长了,不是吗
编辑:将问题更新为更具体的问题。
谢谢!
使用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>]
Ack!矩形不是正方形!这里有一个更好的方法来做同样的事情:
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>]
通过在类本身上创建实例变量和accesor方法—它恰好是Class
类的实例,类似于MyClass = Class.new
—类的所有实例(以及外部实例)都有一个公共的、干净的位置来读取/写入其他类之间不共享的信息。
请注意,显式跟踪创建的每个实例将防止对"未使用"实例进行垃圾收集。小心使用类似上面的代码
以更干净的方式使用class_eval
最后,如果您要使用class_eval
,请注意,它还有一个块形式,不必解析和lex字符串来评估它:
Foo.class_eval('@@bar') # ugh
Foo.class_eval{ @@bar } # yum