ruby - 请解释一下 ruby​​ 的这种元编程魔法

标签 ruby metaprogramming

module HashInitialized
  def hash_initialized(*fields)
    define_method(:initialize) do |h|
      missing = fields - h.keys
      raise Exception, "Not all fields set: #{missing}" if missing.any?

  h.each do |k,v|
    instance_variable_set("@#{k}", v) if fields.include?(k) 
    end
   end
 end
end

class Cheese
  extend HashInitialized
  attr_accessor :color, :odor, :taste
  hash_initialized :color, :odor, :taste
end

好的,我的理解是:

  1. 我们用 HashInitialized 中的方法扩展 Cheese 类,因此模块 HashInitialized 中的 hash_initialized 方法可用作 Cheese 中的类方法
  2. 我们将 3 个符号传递给 hash_initialized 方法
  3. 在 hash_initialized 方法中,由于 * 运算符,这 3 个符号被放入称为字段的数组中
  4. 在hash_initialized方法中我们定义了初始化方法
  5. 现在是我不明白的部分,|h| 是什么?指的是?为什么我们可以在 |h| 上调用 h.keys。好像是 Hash,但我不知道它是如何传递到那里的。
  6. 然后我们迭代这个|h| hash,设置实例变量,这里就很清楚了,除了|h|响应每个,因此它必须是数组或哈希,但我仍然不明白这些值从何而来。

感谢任何帮助!

代码取自 ruby​​monk.com,元编程 Ruby:Ascent

最佳答案

define_method(:initialize) do |h|... 使用一个参数 (h) 创建了一个初始化方法。这意味着它创建了一个期望散列的构造函数。想象一下,创建的代码如下所示:

class Cheese

  def initialize(h)
    missing = fields - h.keys
    raise Exception, "Not all fields set: #{missing}" if missing.any?

    h.each do |k,v|
      instance_variable_set("@#{k}", v) if fields.include?(k) 
    end
  end
end

关于ruby - 请解释一下 ruby​​ 的这种元编程魔法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22070774/

相关文章:

ruby - 如何从 ruby​​ 中取消转义 c 风格的转义序列?

ruby-on-rails - 检查来自另一个对象的 ruby​​ 枚举

ruby - 在运行时向 ruby​​ 模块添加类

grails - 是否可以将命名查询元编程到 grails 域类上?

javascript - 描述两组数据之间的转换... "meta-transform"?

ruby-on-rails - 在 Ruby on Rails 3 应用程序中实现设置的首选方法是什么?

ruby - rvm : Failed to create the file bin-ruby-2. 6.3.tar.bz2.part:权限被拒绝

ruby - cucumber / ruby : Different table console output and Jenkins

c++ - 如何确定可调用对象的函数签名?

c++ - 我如何使用比率而不是 float ?