【问题标题】:Inherit a new class method at runtime在运行时继承一个新的类方法
【发布时间】:2012-02-24 08:36:58
【问题描述】:

在 Ruby 中,<ClassName>.constants 对于检查类很有用:

> Numeric.constants(false)
=> [:KILOBYTE, :MEGABYTE, :GIGABYTE, :TERABYTE, :PETABYTE, :EXABYTE]
> Object.constants(false)
=> [:Object, :Module, ...]

这是在Module中定义的:

> Object.method(:constants)
=> #<Method: Class(Module)#constants>

我想添加另一种方法来打印包含所有常量及其值的哈希。到目前为止的结果如下:

def Module.constants_hash(inherit=true)
    self.constants(inherit).inject({}) do |hash, constant|
        hash[constant] = self::const_get(constant)
        hash
    end
end

这适用于Module(虽然它没有常量,所以结果只是一个空哈希),但它不是继承的

> Object.constants_hash(false)
NoMethodError: undefined method `constants_hash' for Object:Class
from (pry):117:in `<main>'

我当然可以将代码中的类名更改为例如Object 使调用工作,但是是否有可能使所有依赖模块也继承新方法?换句话说,是否可以在运行时添加一个方法,然后由 require 修改后的类继承?

我宁愿不要重载原始的Module.constants,以避免更改 API。

【问题讨论】:

    标签: ruby inheritance metaprogramming


    【解决方案1】:

    ObjectClass 类型的实例。 Class 类继承自 Module。为了使Object.constants_hash 工作,您需要定义ClassModule 类的instance 方法:

    class Module
      def constants_hash(inherit=true)
          self.constants(inherit).inject({}) do |hash, constant|
              hash[constant] = self::const_get(constant)
              hash
          end
      end
    end
    

    在您的代码中,您只需将constants_hash 添加到Module 实例(Class 类型)的单例类,这就是您没有得到预期结果的原因。

    【讨论】:

    【解决方案2】:

    通过在模块中声明此方法,然后根据需要将其混合到每个上下文中,您可能会获得更好的运气:

    module ConstantsHash
      def constants_hash(inherit = true)
        Hash[
          self.constants(inherit).collect do |constant|
            [ constant, const_get(constant) ]
          end
        ]
      end
    end
    
    Module.extend(ConstantsHash)
    Object.extend(ConstantsHash)
    
    puts Object.constants_hash.inspect
    

    请注意,在这种情况下,使用 Hash[] 而不是 inject({ }) 似乎效果更好。

    【讨论】:

    • 能否请您提供参考或简单解释为什么Hash[] 可能比inject({ }) 更好?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-11-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-02-14
    相关资源
    最近更新 更多