在类方法中使用实例变量 - Ruby

时间:2012-02-16 12:34:00

标签: ruby instance-variables

我对ruby很新(我实际上是c#dev。),所以这个问题可能是一个菜鸟。 我有一个像下面这样的类,我使用实例变量(数组)来避免使用大量的方法参数。

它按照我的预期工作,但这是一个很好的做法吗? 实际上我不希望它有用,但我想类方法在其他语言中不能作为静态方法工作,所以我想知道这是不是一个好的做法,或者我是否会遇到诸如将这些变量作为类变量和乱码的问题一切都好了。

class DummyClass
  def self.dummy_method1
    @arr = []
    # Play with that array
  end

  def self.dummy_method2
    # use @arr for something else
  end
end

2 个答案:

答案 0 :(得分:66)

实例变量在Ruby中对类起作用的原因是Ruby类本身是实例(类Class的实例)。通过检查DummyClass.class来亲自尝试。在Ruby中,C#意义上没有“静态方法”,因为每个方法都定义在(或继承到)某个实例上并在某个实例上调用。因此,他们可以访问被调用者碰巧可用的任何实例变量。

由于DummyClass是一个实例,它可以有自己的实例变量。您甚至可以访问这些实例变量,只要您有对类的引用(这应该始终是因为类名是常量)。在任何时候,您都可以调用::DummyClass.instance_variable_get(:@arr)并获取该实例变量的当前值。

至于这是否是一件好事,取决于方法

如果@arr逻辑上是实例/类DummyClass的“状态”,则将其存储在实例变量中。如果@arr仅在dummy_method2中用作操作快捷方式,则将其作为参数传递。举一个使用实例变量方法的例子,考虑Rails中的ActiveRecord。它允许你这样做:

u = User.new
u.name = "foobar"
u.save

此处,分配给用户的名称是合法用户的数据。如果在#save通话之前,有人要问“此时用户的名字是什么”,你会回答“foobar”。如果你在内部挖掘得足够深(你会深入挖掘并进入很多元编程,你会发现它们正是使用实例变量)。

我使用的示例包含两个单独的公共调用。要查看尽管只进行了一次调用仍然使用实例变量的情况,请查看#update_attributes的ActiveRecord实现。方法体只是load(attributes, false) && save。为什么#save没有传递任何参数(比如新的name),即使它会在UPDATE users SET name='foobar' WHERE id=1;之类的保存体中?这是因为名称之类的东西是属于实例的信息。

相反,我们可以看一下实例变量无用的情况。查看#link_to_if的实现,该方法接受boolean-ish参数(通常是源代码中的表达式)以及#link_to通常接受的参数,例如要链接的URL。当布尔条件为真时,它需要将其余参数传递给#link_to并调用它。在这里分配实例变量没有多大意义,因为你不会说这里的调用上下文(渲染器)在实例中包含了这些信息。渲染器本身没有“链接到的URL”,因此,它不应该隐藏在实例变量中。

答案 1 :(得分:21)

这些是类实例变量,并且在ruby中是完全合法的东西:类也是对象(类的实例),因此有实例变量。

要注意的一件事是每个子类都有自己的一组类实例变量(在所有这些都是不同的对象之后):如果你继承了DummyClass,那么子类上的类方法将无法见@arr

类变量(@@foo)当然是相反的:整个类层次结构共享相同的类变量。