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”。如果你深入到内部(你需要很深入并进行大量元编程),你会发现它们确实使用实例变量来做到这一点。
我使用的示例包含两个单独的公共调用。要查看一个即使只进行了一个调用也仍然使用实例变量的情况,请查看ActiveRecord实现的
#update_attributes
。该方法体简单地为
load(attributes, false) && save
。为什么
#save
没有传递任何参数(比如新的
name
),即使它将在保存的主体中出现,例如
UPDATE users SET name='foobar' WHERE id=1;
? 这是因为像名称这样的信息属于实例。
相反,我们可以看一个例子,其中实例变量没有使用意义。看看
#link_to_if
的实现,这个方法接受一个布尔值参数(通常是源代码中的表达式),以及
#link_to
通常接受的参数,例如链接到的URL。当布尔条件为真时,它需要将其余的参数传递给
#link_to
并调用它。在这里分配实例变量并没有太多意义,因为您不会说调用上下文(渲染器)在实例中包含该信息。渲染器本身没有“链接到的URL”,因此不应该被埋藏在实例变量中。