我忘记了Ruby中的x = y
使得x引用与y相同的对象,我被咬了几次;在Ruby术语中,我已经习惯了语言,x = y.dup
。忘掉这一点,当我认为在作业的右侧是安全的时候,我无意中改变了y
。
我可以看到,在没有特殊原因的情况下避免简单的x = y
任务是有意义的,但同样的事情可能潜伏在其他地方,如
name = (person.last_name.blank? ? 'unknown' : person.last_name)
后面的name << title
实际上会改变person.last_name而不只是名字。
如果这也发生在你身上,你是如何学会避免它的?是否有某些红旗或图案需要寻找?你对每个作业都怀疑吗?你经常使用.dup
吗?我不知道Ruby的使用是否会成为我的第二天性,所以任何有用的提示都会受到欢迎。
答案 0 :(得分:5)
这在像Ruby这样的(基本上是命令性的)语言中可能听起来不正统,但我的建议是:通过不更新对象来避免附带损害(除非是绝对必要的);而是创建新的。你付出了一些性能,但你会得到更清晰,更紧凑,更模块化,更容易调试的代码。
http://en.wikipedia.org/wiki/Functional_programming
因此,在您的示例中,只需使用新名称创建一个新字符串:
complete_name = name + title
答案 1 :(得分:1)
只是对tokland答案的补充:
功能方法坚持immutability - 即不改变现有对象,而是在想要更改原始对象时创建另一个对象。这有点违背了Ruby也带来的面向对象的范例(对象在内部保持状态,可以通过调用方法来改变它),所以你必须在两种方法之间取得平衡(另一方面,我们受益通过一种语言可以轻松访问多种范例。)
所以,现在要记住三件事:
y=x
时,您只是说“我们为名为y
的任何内容提供了另一个名称x
。”name << title
变更名为name
的对象。name += title
获取名为name
和title
的对象,将它们连接到另一个对象,并指定新对象名name
。它不会改变任何东西。答案 2 :(得分:0)
我也遇到过这样的情况而且它导致了一个错误,我花了半天才弄明白。我基本上做了这样的事情
hash = {....}
filename = object.file_name
hash.each |k, v| {file_name.gsub!(k, v) if file_name.include? k}
这段代码在循环中,在循环中,我期望变量file_name
再次设置为原始值。但是,当我执行file_name.gsub!
时,object.file_name已更改。有两种方法可以解决这个问题。将.gsub!
来电替换为file_name = file_name.gsub
或file_name = object.file_name.dup
。我选择了第二种选择。
我认为我们应该谨慎使用!
和<<
的方法,因为它们会更改他们正在行动的原始对象,尤其是在这样的作业之后。
答案 3 :(得分:0)
方法不应修改变量(例如,通过使用移位运算符),除非其定义表明它将修改它。
所以:永远不要修改一个没有(a)创建它的方法中的对象,或者(b)修改它修改它的文档。