3

我只是想了解destroy以下代码中方法的行为:

更新:请注意,我的目的是了解行为,而不是将 nil 分配给变量的直接解决方案。

    def conf
      @conf ||= { 'foo' => { 'bar' => 'baz' } }
    end

    def destroy
      conf = nil
    end

    def change
      conf['foo']['bar'] = 'meh'
    end

    def add
      conf['foo']['abc'] = 'moo'
    end

这是调用该add方法的输出:

    add
    pp conf
    # {"foo"=>{"bar"=>"baz", "abc"=>"moo"}}

change方法

   change
   pp conf
   # {"foo"=>{"bar"=>"meh"}}

destroy方法

   destroy
   pp conf
   # {"foo"=>{"bar"=>"baz"}}

那么,为什么不destroy导致conf拥有nil

另一个相关的片段,这次是标量而不是哈希:

    def foo
      @foo ||= "bar"
    end

    def destroyfoo
      foo = nil
    end

    def changefoo
      foo = "baz"
    end

调用时的结果changefoodestroyfoo两者:

    destroyfoo
    puts foo
    # "bar"

...

    changefoo
    puts foo
    # "bar"

在这两种情况下,任何关于可能发生的事情的指示都会很有用。

4

2 回答 2

2

您的destroy,destroyfoochangefoo方法都只是分配给局部变量,不会导致调用访问器方法。

change方法有效的原因conf['foo']['bar'] = 'meh'是调用confget 方法@conf,然后调用[]返回对象上的方法,然后调用[]=第一级哈希上的方法。同样对于add.

这与直接分配不同,例如conf =

另外,为了完整起见,请注意,即使您为@conf(使用attr_writer或通过自己编写conf=方法)创建了一个 attr 编写器,那么类似的行conf = nil仍然会引用局部变量并且不会调用您的方法。您需要使用self.conf=才能消除歧义。

于 2012-11-29T15:02:34.433 回答
1

这是因为您的destroy方法正在创建一个名为conf. Ruby 能够根据你如何调用它来判断什么是方法,什么是变量。

irb> puts "Lincoln"
Lincoln
irb> puts = "Washington"
irb> puts "Polk"
Polk
irb> puts puts 
Washington

这里发生的事情是有一个方法被调用puts,并且有一个变量被调用puts。Ruby 根据您调用它的方式确定您尝试使用哪个。在最后一个例子中,左边puts是方法调用,右边puts是变量。

请注意,destroy一旦方法块执行完毕,变量创建将退出范围。因此,在您的情况下,尝试在conf方法之外的任何时间(在主范围内)调用将是对该方法的调用。

于 2012-11-29T14:59:48.613 回答