为什么不调用此属性编写器?

时间:2016-12-25 03:53:21

标签: ruby setter

代码:

class Weird
  DEFAULT_FOO = 'fo0'

  attr_accessor :foo

  def initialize(val)
    @foo = val
  end

  def run
    unless foo
      foo = DEFAULT_FOO         # Fails
      # @foo = DEFAULT_FOO      # Works
    end

    bar(foo)
  end

  def bar(f)
    puts "The foo is '#{f}'"
  end
end

RSpec.describe Weird do
  subject(:weird) do
    described_class.new(foo_val)
  end
  let(:foo_val) { nil }

  describe '#run' do
    context 'without foo' do
      it 'bars the foo' do
        expect(subject).to receive(:bar).with(described_class::DEFAULT_FOO)
        subject.run
      end
    end

    context 'with foo' do
      let(:foo_val) { 'quux' }

      it 'bars the foo' do
        expect(subject).to receive(:bar).with(foo_val)
        subject.run
      end
    end
  end
end

使用RSpec(rspec weird.rb)运行此操作,第二次测试失败并显示:

  1) Weird#run with foo bars the foo
     Failure/Error: bar(foo)

       #<Weird:0x007fc1948727f8 @foo="quux"> received :bar with unexpected arguments
         expected: ("quux")
              got: (nil)
       Diff:
       @@ -1,2 +1,2 @@
       -["quux"]
       +[nil]

     # ./test_case_2.rb:21:in `run'
     # ./test_case_2.rb:48:in `block (4 levels) in <top (required)>'

未调用隐式定义的foo=()属性编写器方法;明确定义一个也不起作用。相反,它似乎是一个方法 - 局部变量foo正在创建(和设置)它不应该的地方。为什么会这样?

Ruby版本为ruby 2.2.2p95 (2015-04-13 revision 50295) [x86_64-darwin15]

2 个答案:

答案 0 :(得分:1)

foo = DEFAULT_FOO失败,因为这是创建局部变量foo并为其指定值DEFAULT_FOO。但是,当您调用bar(foo)时,它会首先查找@值,在这种情况下仍为零。

分配实例变量时,您必须使用self.foo =@foo =

答案 1 :(得分:0)

2种修复方式

  1. 使用self.foo = DEFAULT_FOO
  2. 使用@foo = DEFAULT_FOO