gpt4 book ai didi

ruby - 避免改变参数的最佳实践?

转载 作者:太空宇宙 更新时间:2023-11-03 17:31:38 25 4
gpt4 key购买 nike

有人可以建议一个好的、ruby-idiomatic 的方法来避免这种情况吗?

class Foo
attr_accessor :bar
end

a = {one: 1}
x = Foo.new; x.bar = a

x.bar[:two] = 2
p a #=> {one: 1, two: 2}
  • 我可以简单地不允许某个类的用户访问它的属性,这解决了问题……在本例中。 (将参数传递给方法怎么样?)无论如何,除了 attr_reader 之外,避免一切,并且仅在非可变属性上使用它,看起来不太像 Ruby。

  • 或者,我不能编写任何改变值的代码,这很吸引人,但在 Ruby 中并不容易做到。

  • 我可以系统地dupclone我的类的每个参数都给出了——除了那些方法对 Nilclass、Fixnums、Symbols 等不起作用——更糟糕的是,responds_to?(:dup) == true对于那些类型。 (另外,dupclone 都没有进行深度复制。)

在上面的例子中我修改了bar调用者中的属性,但如果代码在类中,或者如果我在类上使用方法而不是 attr_accessor,问题仍然相同:如果我想要一个可以接受一个值并用它做一些事情的类,并且如果出于某种原因我必须通过在某处改变该值来做到这一点——ruby 中是否有一种惯用的方法来确保我不会感染具有该突变值的调用者?

在 Ruby 中,我们应该不太关心传入数据的类型,但看起来我必须非常关心它才能告诉我如何使这个值安全地变异。如果它是 NullObject 或 Fixnum 或 Symbol 没问题,否则我可以 dup它...除非我需要深复制它。

这不可能吧?


编辑:经过更多思考

Sergio 当然是对的——有时您想要这种行为。并不是因为在您的代码中使用副作用是个好主意,而是因为有时您要向其传递消息的类需要对某个对象的实时引用,该对象之后可能会发生变化。

只有当您传递 Enumerable 时,此行为才会出现问题。如果我传递一个 Array 或 Hash,我真的不希望接收者修改它。所以我的结论是:

  • 每当我将东西传递给接收者时,按照 Sergio 所说的进行防御性编码,以防编写代码的人不小心。
  • 在我自己的类(class)中实现一条总括规则:复制所有传入的 Enumerables。

最佳答案

调用者有责任保护自己不受被调用代码的影响。比方说,您有一些命令行选项解析代码。你得到了这个参数散列,你想做一些验证(或其他)。现在,验证代码是由其他一些喜欢就地做事以“提高效率”的人编写的。所以很可能你的哈希会发生变异,你以后将无法使用它。

解决方案?传递一份副本

validate_params! Marshal.load(Marshal.dump(params)) # deep copy

请注意,在某些情况下,突变是需要的。所以一定是调用者控制了效果(允许或阻止)。

关于ruby - 避免改变参数的最佳实践?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34201310/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com