为什么我能用破坏性方法修改变量超出范围?

时间:2013-02-13 06:27:22

标签: ruby

class PassByValueScopeConfusion

  def does_not_modify(s)
    s = "DIFFERENT"
  end

  def does_modify(s)
    s.upcase!
  end

end

obj = PassByValueScopeConfusion.new

some_string = "abcdefg"

# does not change the value of some_string
obj.does_not_modify(some_string)

# changes the value of some_string
obj.does_modify(some_string)

我将一个字符串传递给一个方法,该方法在传入的字符串中调用破坏性方法,不知何故,原始变量“some_string”被修改。如果我能够使用破坏性方法修改范围之外的“some_string”变量,是否有办法使用赋值运算符(除了调用replace方法之外)?

编辑如果Ruby不允许使用赋值运算符,为什么Ruby允许使用破坏性运算符修改范围之外的变量?

3 个答案:

答案 0 :(得分:1)

这两种情况之间存在差异。

s.upcase!

这意味着“修改引用s所指向的对象的状态”。

s = "DIFFERENT"
另一方面,这意味着“将对象的引用指向一个完全不同的对象”(或“如果您愿意,将名称绑定到另一个对象”)。创建了新对象s,该对象遮蔽了外部s。你无法以这种方式修改外部对象。

答案 1 :(得分:0)

您正在传入指向字符串对象的引用。

因此在do_not_modify示例中,当调用时,s包含指向包含字符串“abcdefg”的某个内存地址的指针。然后,您可以将引用的值更改为指向内存中保存新字符串“DIFFERENT”的新的不同位置。然而,调用者代码仍然继续指向原始字符串“abcdefg”的原始位置

在does_modify示例中,s包含指向包含字符串“abcdefg”的某个内存地址的指针。 upcase函数直接修改这部分内存并将每个字符更改为“ABCDEFG”。调用代码指向同一个内存地址,因此在函数返回后会保持更改。

答案 2 :(得分:0)

  

为什么Ruby允许修改范围之外的变量

没有。您不修改变量,而是修改变量指向的对象。