在类方法中使用实例变量 - Ruby
Posted
技术标签:
【中文标题】在类方法中使用实例变量 - Ruby【英文标题】:Using Instance Variables in Class Methods - Ruby 【发布时间】:2012-03-07 20:31:18 【问题描述】:我有一个类似下面的类,我使用实例变量(数组)来避免使用大量方法参数。
它按我的预期工作,但这是一个好习惯吗? 实际上我不认为这会起作用,但我猜类方法在其他语言中不能作为静态方法工作。
class DummyClass
def self.dummy_method1
@arr = []
# Play with that array
end
def self.dummy_method2
# use @arr for something else
end
end
【问题讨论】:
【参考方案1】:实例变量在 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
的实现,该方法接受布尔型参数(通常是源代码中的表达式)以及#link_to
通常接受的参数,例如要链接到的URL。当布尔条件为真时,它需要将其余参数传递给#link_to
并调用它。在这里分配实例变量没有多大意义,因为您不会说这里的调用上下文(渲染器)在实例中包含该信息。渲染器本身没有“链接到的 URL”,因此,它不应该被埋在实例变量中。
【讨论】:
感谢您通过示例进行了精彩的解释,尤其是关于这是否是一种好的做法。【参考方案2】:这些是类实例变量,在 ruby 中是完全合法的东西:类也是对象(类的实例),因此也有实例变量。
需要注意的一点是,每个子类都会有自己的一组类实例变量(毕竟这些都是不同的对象):如果子类化DummyClass
,子类上的类方法将无法看到@ 987654322@.
类变量 (@@foo
) 当然反过来:整个类层次结构共享相同的类变量。
【讨论】:
嗯,那是不同的东西。所以只要我不继承一个新类,这没什么好担心的。这是个好消息,谢谢! 感谢您的澄清!多年来一直在做 Ruby,现在不知何故刚刚遇到类实例变量。这对于准确了解正在发生的事情非常有帮助。以上是关于在类方法中使用实例变量 - Ruby的主要内容,如果未能解决你的问题,请参考以下文章