【问题标题】:Understanding Ruby define_method with initialize用初始化理解 Ruby define_method
【发布时间】:2020-08-22 10:31:23
【问题描述】:

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

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

我知道 Ruby 中的 define_method 方法可以“即时”创建方法,这很棒。现在,在本教程中,用于从类中实例化对象的方法 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

接下来,在另一个类的初始化程序中,首先使用Foo.define_initialize(attributes) 调用此方法,其中属性是来自CSV 文件的标题行,例如["attr_1", "attr_2", ...],因此尚未提供*args

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

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

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

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

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

因为否则,它必须抛出诸如“缺少参数”之类的异常 - 因此,换句话说,它只是定义顾名思义的方法。

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

感谢任何有用的回复!

【问题讨论】:

  • 是的,就是这样
  • 错字警告:Class Foo 应该是 class Foo。请注意,由于(原文如此)Ruby v2.1,Foo#initialize 将是 private,即使您没有在 define_method 中指定它。另外,请考虑这个替代 conStruct

标签: ruby metaprogramming


【解决方案1】:

短答案,是的,长答案:

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

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

【讨论】:

  • 感谢您的回答,是的,我认为这也是我理解元编程的方式以及您对更新/创建钉子的解释。只是有时我必须改变我的思维方式并逐步通过代码来真正理解我如何通过创建一个动态更新基本方法的方法来构建或更新方法:D
  • 补充一下 Andres 所说的:在第一个和第二个方法定义之间初始化的任何东西都将使用第一个初始化方法,而不是第二个。
猜你喜欢
  • 1970-01-01
  • 2016-07-10
  • 1970-01-01
  • 2012-06-15
  • 2011-03-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-03-20
相关资源
最近更新 更多