理解 Ruby define_method 和初始化

Understanding Ruby define_method with initialize

所以,我目前正在 Ruby 学习元编程,我想完全了解幕后发生的事情。

我遵循了一个教程,在该教程中我将一些方法包含在我自己的小项目中,一个 CSV 文件的导入器,但我很难掌握所使用的其中一种方法。

我知道 Ruby 中的 define_method 方法可以“即时”创建方法,这很棒。现在,在教程中,从 class 实例化 object 的方法 initialize 是使用此方法定义的,所以基本上它看起来像这样:

class Foo
    def self.define_initialize(attributes)
      define_method(:initialize) do |*args| 
       attributes.zip(args) do |attribute, value|
         instance_variable_set("@#{attribute}", value)
       end
      end
    end
end

接下来,在另一个 class 的初始化程序中,首先使用 Foo.define_initialize(attributes) 调用此方法,其中属性是 CSV 文件中的 header 行,如 ["attr_1", "attr_2", ...] , 所以 *args 还没有提供。

然后在下一步中循环遍历数据:

@foos = data[1..-1].map do |d|
  Foo.new(*d)
end

所以这里 *d 作为 *args 分别传递给初始化方法到块。

那么,当 Foo.define_initialize 被调用时,该方法只是为以后调用 class 而“构建”的,对吗? 所以我理论上得到一个 class 现在有这样的方法:

def initialize(*args)
  ... do stuff
end

因为否则,它必须抛出一个异常,如“缺少参数”或其他东西 - 所以,换句话说,它只是 定义 顾名思义的方法。

我希望我的问题足够清楚,因为作为来自 "Rails magic" 的 Rails 开发人员,我真的很想在某些情况下了解幕后发生的事情:)。

感谢任何有帮助的回复!

简答,是,长答:

首先,让我们开始以非常(非常)简单的方式解释元编程如何在 Ruby 上工作。在 Ruby 中,任何事物的定义永远不会关闭,这意味着您可以随时添加、更新或删除任何事物(实际上,几乎任何事物)的行为。所以,如果你想添加一个方法到 Object class,你是允许的,删除或更新也是如此。

在您的示例中,您只是更新或创建给定 class 的 initialize 方法。请注意 initialize 不是强制性的,因为 ruby 会为您构建一个默认的“空白”,如果您没有创建的话。您可能会想,“如果 initialize 方法已经存在会怎样?”答案是“没有”。我的意思是,ruby 将再次重写初始化方法,新的 Foo.new 调用将调用新的 initialize.