我最近遇到一个问题,在Ruby类上调用load
两次导致错误(这里是real-world example)。这是因为在类体中发生了有状态的方法调用,load
导致这些调用被执行两次。一个简单的例子如下:
base.rb
:
class Base
def foo
puts "BASE"
end
end
derived.rb
:
require "./base"
class Derived < Base
alias_method :foo_aliased, :foo
def foo
puts "DERIVED!"
end
end
从REPL执行:
$ load './derived.rb'
> true
$ Derived.new.foo
> DERIVED!
> nil
$ Derived.new.foo_aliased
> BASE
> nil
$ load './derived.rb'
> true
$ Derived.new.foo
> DERIVED!
> nil
$ Derived.new.foo_aliased
> DERIVED!
> nil
在此示例中,第二个load
会导致alias_method
破坏原始别名。因此,我们已经破坏了依赖于原始方法的完整别名的任何代码。
暴力类重新加载很常见(例如,你在使用Spork的RSpec配置的each_run
子句中看到了很多),并不总是很容易禁止直接使用load
。因此,似乎防止错误的唯一方法是确保类定义是“幂等的”。换句话说,无论您调用它们多少次,都要确保从类定义调用的方法应该产生相同的结果。重新加载不会破坏更多代码这一事实似乎暗示了一种不言而喻的惯例。
是否有一些Ruby类设计的样式指南要求这个?如果是这样,执行这些语义的常用技巧是什么?对于某些方法,您可以只执行一些memoization以防止使用相同的参数重新执行相同的方法,但是alias_method
之类的其他内容似乎更难解决。
答案 0 :(得分:1)
你完全错了。假设所有类方法都是幂等的,既不是一个充分的条件,也不是一个代码在多次加载时不会中断的必要条件。
因此,自然而言,没有风格指南来强制执行。