2

我最近遇到了一个问题,load在 Ruby 类上调用两次会导致错误(这是一个真实的示例)。这是因为在类主体中发生了有状态的方法调用,并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破坏了原始别名。结果,我们破坏了任何依赖于原始方法具有完整别名的代码。

蛮力类重新加载很常见(例如,您在each_run使用 Spork 的 RSpec 配置的条款中看到了很多),完全禁止使用并不总是那么容易load。因此,似乎防止错误的唯一方法是确保类定义是“幂等的”。换句话说,您已经确保打算从类定义中调用的方法无论调用多少次都应该产生相同的结果。重新加载不会破坏更多代码的事实似乎暗示了一种不言而喻的约定。

是否有一些针对 Ruby 类设计的风格指南要求这样做?如果是这样,执行这些语义的常用技术是什么?对于某些方法,您可以只做一些记忆以防止使用相同的参数重新执行相同的方法,但其他一些事情alias_method似乎更难解决。

4

1 回答 1

1

你完全错了。假设所有类方法都是幂等的,这既不是代码在多次加载时不会中断的充分条件,也不是必要条件。

因此,很自然地没有样式指南可以强制执行。

于 2013-02-24T07:10:50.093 回答