【问题标题】:What does it mean that `attr_accessor` / `attr_reader` create an instance variable?`attr_accessor` / `attr_reader` 创建实例变量是什么意思?
【发布时间】:2017-10-21 21:05:20
【问题描述】:

attr_accessor 的文档明确指出它创建了一个实例变量:

[...] 创建实例变量 (@name) 和相应的访问方法 [...]

attr_reader 的文档也是如此:

创建实例变量和相应的方法 [...]

我了解第二部分,即 attr_accessorattr_reader 创建方法,但我不明白第一部分。

他们“创建实例变量”是什么意思?

【问题讨论】:

  • 请务必记住,ruby-doc.org 并非由 Ruby 核心团队维护。它有时推测某些事情应该是稳定的,而官方没有这样的说法。其他时候,它推测有关实现的事情是不正确的。
  • @ndn:这些年来我一直认为 ruby​​-doc 是从源代码 cmets 自动生成的。你说不是这样吗? :mindblast:
  • @SergioTulentsev,you appear to be correct,(虽然它仍未由核心团队维护)。所以代码中的注释就错了……
  • @ndn:如果我们想学究气,技术上是错误的。也许 cmets 的作者意味着更笼统。 “创建实例变量”,如“匹配此访问器名称的实例变量,将在对象生命周期的某个时刻成为事物”。或者我在这里玩得太多了:)
  • @ndn:看来我们要为 14 年前写的那条评论负责。我们可以在推特上问他什么的:)

标签: ruby instance-variables attr-accessor


【解决方案1】:

这是文档中的错误/误导性措辞。 attr_reader/attr_accessor 本身不会创建任何变量。他们怎么能?它们在类实例生命周期之外工作。甚至读访问也不能使实例变量变得生动。只有写入权限才能创建它们。

class Foo
  attr_accessor :bar
end

foo = Foo.new
foo.instance_variables # => []
foo.bar # try read ivar
foo.instance_variables # => [], nope, not yet
foo.bar = 2 # write ivar
foo.instance_variables # => [:@bar], there it is

【讨论】:

  • 从技术上讲,访问者可以例如在初始化过程中添加一个步骤,将所述实例变量设置为nil。但正如你所展示的,情况并非如此。
【解决方案2】:

attr_accessor 的文档明确指出它创建了一个实例变量:

[...] 创建实例变量 (@name) 和相应的访问方法 [...]

attr_reader 的文档也是如此:

创建实例变量和相应的方法 [...]

我了解第二部分,即 attr_accessorattr_reader 创建方法,但我不明白第一部分。

他们“创建实例变量”是什么意思?

如果不是完全错误的话,该文档至少具有误导性。他们创造方法,仅此而已。在大多数 Ruby 实现中,实现是使用宿主语言(例如 C 表示 YARV,Java 表示 JRuby)对实现内部的特殊访问权限,但实际上,您可以用纯 Ruby 编写它们:

class Module
  def attr_reader(*attrs)
    attrs.each do |attr|
      define_method(attr) do
        instance_variable_get(:"@{attr}")
      end
    end
  end

  def attr_writer(*attrs)
    attrs.each do |attr|
      define_method(:"{attr}=") do |val|
        instance_variable_set(:"@{attr}", val)
      end
    end
  end

  def attr_accessor(*attrs)
    attr_reader(*attrs)
    attr_writer(*attrs)
  end
end

【讨论】:

  • YARV 的实现还执行检查:如果属性名称不是有效的实例变量名称,则会引发 NameError。例如:attr_reader '1' 结果为 invalid attribute name `1'。也许文档指的是那个检查。
猜你喜欢
  • 2020-01-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-03-05
  • 2011-06-30
  • 2017-12-06
  • 1970-01-01
相关资源
最近更新 更多