【发布时间】: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