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

tac*_*rry 54 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
Run Code Online (Sandbox Code Playgroud)

Ste*_*ven 72

实例变量在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
Run Code Online (Sandbox Code Playgroud)

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

我使用的示例包含两个单独的公共调用.要查看尽管只进行了一次调用仍然使用实例变量的情况,请查看ActiveRecord实现#update_attributes.方法体很简单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",因此,它不应该隐藏在实例变量中.

  • 感谢您通过示例进行了精彩的解释,特别是关于这是否是一个好的做法。 (2认同)

Fre*_*ung 25

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

需要注意的一点是,每个子类都有自己的一组类实例变量(在所有这些都是不同的对象之后):如果你进行了子类化DummyClass,那么子类上的类方法将无法看到@arr.

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