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

这和我预想的一样,但这是一个好的做法吗?

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

  def self.dummy_method2
    # use @arr for something else
  end
end

推荐答案

在Ruby中,实例变量作用于类的原因是Ruby类本身有are个实例(类Class的实例).通过判断DummyClass.class,自己try 一下.Ruby中没有C#意义上的"静态方法",因 for each 方法都在某个实例上定义(或继承到某个实例中),并在某个实例上调用.因此,它们可以访问被调用方上碰巧可用的任何实例变量.

因为DummyClass是一个实例,所以它可以有自己的实例变量.你甚至可以访问这些实例变量,只要你有一个类的引用(这应该是因为类名是常量).在任何时候,您都可以调用::DummyClass.instance_variable_get(:@arr)并获取该实例变量的当前值.

至于这是否是一件好事,it depends on the methods.

如果@arr在逻辑上是实例/类DummyClass的"状态",则将其存储在实例变量中.如果@arr仅在dummy_method2中用作操作快捷方式,则将其作为参数传递.举一个例子,在这里使用实例变量方法,考虑Rails中的ActureCordRD.它允许您执行以下操作:

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

在这里,已分配给用户的名称是用户合法拥有的数据.如果在拨打#save之前,有人问"此时用户的名字是什么",你会回答"foobar".如果你深入研究内部(你会深入研究很多元编程,你会发现他们使用实例变量来实现这一点).

我使用的示例包含两个独立的公共调用.要了解尽管只进行了一次调用,但仍然使用实例变量的情况,请查看#update_attributes的ActiveRecord实现.方法体就是load(attributes, false) && save.为什么#save没有通过任何参数(比如新的name),即使它将在save where的主体中,比如UPDATE users SET name='foobar' WHERE id=1;?这是因为像名字这样的东西是属于实例的信息.

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

Ruby相关问答推荐

这个#divmod 方法输出这个结果是做什么的?

类 SpecificationPolicy 的超类不匹配

如何从外部获取给定 lambda 的参数值,而不显式返回其绑定?

Ruby 相当于 Groovy 的 Elvis (?:) 运算符?

Encoding::UndefinedConversionError

你喜欢哪种风格的 Ruby 字符串引用?

将字符串与多个模式匹配

我不明白Ruby本地范围(local scope)

Jekyll - 找不到命令

include_examples和it_behaves_like有什么区别?

ActiveSupport::Memoizable 指的是哪种 Ruby memoize 模式?

如何在 Ruby 脚本中运行 Rake 任务?

ruby 中&:运算符的功能是什么?

Ruby 中的Monkey Patching到底是什么意思?

等号 ('=') 放在方法定义中的方法名称之后有什么作用?

在 Ruby 中使用元组?

将哈希传递给函数 ( *args ) 及其含义

为依赖于环境变量的代码编写规范的最佳方法是什么?

如何在Ruby中将字符串拆分为仅具有给定字符的两部分?

JavaScript Array:获取项目的范围