在Ruby中,有没有更好的方法来提取类变量class_eval()



我个人对此没有任何反对意见,除了它很长,但真正困扰我的是单词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

最新更新