在类方法中使用实例变量 - 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的主要内容,如果未能解决你的问题,请参考以下文章

Ruby高级编程面向对象

java 二

iOS在类内部怎么访问实例变量比较好?

实例局部静态变量(java)

类变量实例变量--python

Java中类方法与实例方法的区别