在Ruby中使用数组联合运算符|=时,为什么必须显式调用self-on-accessor?

在Ruby中使用数组联合运算符|=时,为什么必须显式调用self-on-accessor?,ruby,Ruby,以这门课为例: class MyClass attr_accessor :values, :uniq_values def initialize(value) self.uniq_values = ['default_value'] self.values = ['default_value'] copy_value(value) add_value(value) end def copy_value(value) uniq_valu

以这门课为例:

 class MyClass
  attr_accessor :values, :uniq_values

  def initialize(value)
    self.uniq_values = ['default_value']
    self.values = ['default_value']
    copy_value(value)
    add_value(value)
  end

  def copy_value(value)
    uniq_values |= [value]
  end

  def add_value(value)
    values << value
  end

  def run
    puts "uniq_values: #{uniq_values}"
    puts "values: #{values}"
  end
end

obj = MyClass.new('poop')
obj.run

# Expect 'uniq_values' and 'values' to be the same
# OUTPUT:
#  uniq_values: ["default_value"]
#  values: ["default_value", "poop"]
class-MyClass
属性访问器:值,:uniq\u值
def初始化(值)
self.uniq_值=['default_值']
self.values=['默认值']
复制_值(值)
增加价值(价值)
结束
def复制_值(值)
uniq|u值|=[值]
结束
def附加值(值)
数值不同


代码中的
uniq\u值
(局部变量)和
self.uniq\u值
(实例变量)不是一回事

使用
@
以实例变量的形式访问attr内容

class MyClass
  attr_accessor :values, :uniq_values

  def initialize(value)
    @uniq_values = ['default_value']
    @values = ['default_value']
    copy_value(value)
    add_value(value)
 end

  def copy_value(value)
    @uniq_values |= value # crash
    # or |= [value] # embed value in array
    # or |= Hash.new value # don't embed Arrays
    # or def copy_value(*values) # splat
    uniq_values = "poor me, here I am forgotten with the next 'end' keyword"
    # uniq_values != @uniq_values, but
    # self.uniq_values == @uniq_values
  end

  def add_value(value)
    @values << value
  end

  def run
    puts "uniq_values: #{@uniq_values}"
    puts "values: #{@values}"
  end
end

obj = MyClass.new('poop')
obj.run
# Crash!
class-MyClass
属性访问器:值,:uniq\u值
def初始化(值)
@uniq_值=['默认值']
@值=['默认值']
复制_值(值)
增加价值(价值)
结束
def复制_值(值)
@uniq_值|=值#崩溃
#或|=[value]#在数组中嵌入值
#或|=Hash.new value#不嵌入数组
#或def copy_值(*值)#splat
uniq_values=“可怜的我,我忘记了下一个‘end’关键字”
#uniq_值!=@uniq_值,但是
#self.uniq_值==@uniq_值
结束
def附加值(值)

@值…不存在,因此必须设置<带有非false的code>
将生成要编写的
true
,与数组或字符串无关。完全出乎意料,谢谢。我仍然感到困惑,因为在赋值给出
['default\u value']
之前,执行
将uniq\u值放入
,这表明它没有被解析为局部变量?但是,在赋值后执行
的uniq_值放入
中,得到
true
,这意味着给定D-side的注释,它就是。@jasondeney赋值创建了一个新的局部变量
uniq_值
,用相同的名称隐藏getter方法
uniq_值
指的是赋值前的方法和赋值后的局部变量。谢谢@stefan。这绝对是一个阴影,我想我的问题是,为什么在赋值时会创建一个新的局部变量,比如说,如果我做了
values=values@jasondeney,为了更直接的比较,这可能会让人非常困惑,Ruby在解析器阶段处理赋值。来自:“局部变量是在解析器遇到赋值时创建的,而不是在赋值发生时创建的”。你必须使用
values=self.values是的,我想把它嵌入一个数组,这是一个输入错误,谢谢!同事们反对使用@syntax来覆盖getter/setter方法。这是一个奇怪的论点,因为你仍然可以覆盖它(并且可能仍然会产生非常奇怪和难以维护的代码)-但是我不知道你的场景(有点异味),而且这也不是最初的问题。所以,使用self来引用实例变量(作用域),否则您将创建一个新的局部变量uniq_values。天哪,我完全没有抓住问题的关键,抱歉。这是一个伟大的发现。无论如何,它是由于害怕无法覆盖getter和setter:)。我个人会坚持使用
@
s。我发现这也让代码更容易理解。