动态添加ruby类方法或实例方法

pur*_*bon 10 ruby metaprogramming class instance

我是Ruby的新手,所以还在学习.我正在研究如何动态添加方法,我成功创建了实例方法,但在创建类方法时却没有成功.

这就是我生成实例方法的方法:

  class B
    def before_method
      puts "before method"
    end

    def self.run(method)
        send :define_method, method do
          before_method
          puts "method #{method}"
        end
    end
  end

  class A < B
    run :m
    run :n
  end
Run Code Online (Sandbox Code Playgroud)

有关创建静态方法的最佳方法的任何想法?

我的最后一项任务是寻找为类方法创建"之前"和"之后"任务的最佳方法.

Zac*_* Xu 25

要动态创建实例方法,请尝试

class Foo
  LIST = %w(a b c)

  LIST.each do |x|
    define_method(x) do |arg|
      return arg+5
    end
  end
end
Run Code Online (Sandbox Code Playgroud)

现在任何Foo实例都有方法"a","b","c".尝试

Foo.new.a(10)
Run Code Online (Sandbox Code Playgroud)

要动态定义类方法,请尝试

class Foo
  LIST = %w(a b c)

  class << self
    LIST.each do |x|
      define_method(x) do |arg|
        return arg+5
      end
    end
  end
end
Run Code Online (Sandbox Code Playgroud)

然后试试

Foo.a(10)
Run Code Online (Sandbox Code Playgroud)


Con*_*ion 8

对象singleton类的实例方法是对象本身的单例方法.所以,如果你这样做

class B
  def self.run(method)
    singleton_class = class << self; self; end
    singleton_class.send(:define_method, method) do
        puts "Method #{method}"
    end
  end
end
Run Code Online (Sandbox Code Playgroud)

你现在可以打电话了

B.run :foo
B.foo 
=> Method foo
Run Code Online (Sandbox Code Playgroud)

(编辑:根据Lars Haugseth的评论补充B.run:foo)


tad*_*man 2

这是为了使用类方法而重新设计的内容:

class B
   def self.before_method
     puts "before method"
   end

  def self.run(method)
    define_singleton_method(method) do
      before_method
      puts "method #{method}"
    end
  end
end
Run Code Online (Sandbox Code Playgroud)

更新:define_singleton_method从 Ruby 1.9开始使用,它正确分配给eigenclass

  • 这可能不是您想要的:您现在已将该方法添加到 Class 中,这意味着它在*每个*类中都可用(B.class == Class)。这是一个问题,特别是因为并非每个类都有“before_method”。尝试调用 B.run 'foo',定义类 A 并调用 A.foo。它将失败并显示“NameError:未定义的局部变量或方法‘before_method’ for A:Class’” (2认同)
  • 我认为人们在 Ruby 中创建动态方法相当频繁;这就是很多“魔法”的来源。我是否混淆了术语? (2认同)