如何使用define_method创建类方法?

Chi*_*aur 106 ruby metaprogramming class-method

如果您尝试以元编程方式创建类方法,这将非常有用:

def self.create_methods(method_name)
    # To create instance methods:
    define_method method_name do
      ...
    end

    # To create class methods that refer to the args on create_methods:
    ???
end
Run Code Online (Sandbox Code Playgroud)

我的回答是......

fgu*_*len 192

我认为在Ruby 1.9中你可以这样做:

class A
  define_singleton_method :loudly do |message|
    puts message.upcase
  end
end

A.loudly "my message"

# >> MY MESSAGE
Run Code Online (Sandbox Code Playgroud)

  • 还有`singleton_class.define_method` (4认同)

Vin*_*ert 25

我更喜欢使用send调用define_method,我也想创建一个元类方法来访问元类:

class Object
  def metaclass
    class << self
      self
    end
  end
end

class MyClass
  # Defines MyClass.my_method
  self.metaclass.send(:define_method, :my_method) do
    ...
  end
end
Run Code Online (Sandbox Code Playgroud)

  • 谢谢!绝对有办法让自己更好.但是,如果您正在开发一个开源插件,我认为不使用`metaclass`阻塞命名空间更好,所以很高兴知道简单,独立的简写. (2认同)

Jos*_*ber 10

这是Ruby 1.8+中最简单的方法:

class A
  class << self
    def method_name
      ...
    end
  end
end
Run Code Online (Sandbox Code Playgroud)


Chi*_*aur 8

源自:JayWhy,他们也提供了使这个更漂亮的方法.

self.create_class_method(method_name)
  (class << self; self; end).instance_eval do
    define_method method_name do
      ...
    end
  end
end
Run Code Online (Sandbox Code Playgroud)

更新:来自VR的贡献如下; 一个更简洁的方法(只要你只用这种方法定义一个方法),它仍然是独立的:

self.create_class_method(method_name)
  (class << self; self; end).send(:define_method, method_name) do
    ...
  end
end
Run Code Online (Sandbox Code Playgroud)

但请注意,使用send()访问私有方法(如define_method())不一定是个好主意(我的理解是它在Ruby 1.9中消失了).


Art*_*jev 5

如果要根据关注动态定义类方法,可以在Rails中使用:

module Concerns::Testable
  extend ActiveSupport::Concern

  included do 
    singleton_class.instance_eval do
      define_method(:test) do
        puts 'test'
      end
    end
  end
end
Run Code Online (Sandbox Code Playgroud)