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

我有一个类似下面的类,并且我使用了实例变量(数组)来避免使用很多方法参数。

它按我预期的那样工作,但这是一个好习惯吗?实际上,我不希望这样能起作用,但是我想类方法在其他语言中不能作为静态方法工作。

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

  def self.dummy_method2
    # use @arr for something else
  end
end
tackleberry asked 2020-01-19T21:46:38Z
2个解决方案
70 votes

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

由于#link_to是一个实例,因此可以拥有自己的实例变量。 您甚至可以访问那些实例变量,只要您有对该类的引用即可(因为类名是常量,所以应该始终如此)。 在任何时候,您都可以调用#link_to并获取该实例变量的当前值。

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

如果#link_to在逻辑上是实例/类#link_to的“状态”,则将其存储在实例变量中。 如果UPDATE users SET name='foobar' WHERE id=1;仅在UPDATE users SET name='foobar' WHERE id=1;中用作操作快捷方式,则将其作为参数传递。 为了给出使用实例变量方法的示例,请考虑Rails中的ActiveRecord。 它允许您执行以下操作:

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

在此,已分配给用户的名称是用户合法的数据。 如果在致电#link_to之前询问“此时的用户名是什么”,您将回答“ foobar”。 如果您深入研究内部原理(您将深入研究很多元编程,那么您会发现它们恰恰为此使用了实例变量)。

我使用的示例包含两个单独的公共调用。 若要查看仅进行一次调用但仍使用实例变量的情况,请查看ActiveRecord实现#link_to。方法主体为#link_to。为什么#link_to不能传递任何参数(例如新的name),即使它是 将保存在类似UPDATE users SET name='foobar' WHERE id=1;的地方吗? 这是因为诸如名称之类的东西是属于实例的信息。

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

Steven answered 2020-01-19T21:47:28Z
23 votes

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

需要注意的一件事是,每个子类将具有自己的类实例变量集(在所有这些都是不同的对象之后):如果将子类子类化为@@foo,则子类上的类方法将无法看到@arr

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

Frederick Cheung answered 2020-01-19T21:47:58Z
translate from https://stackoverflow.com:/questions/9311347/using-instance-variables-in-class-methods-ruby