如何在不实例化的情况下调用 ruby 对象中的任何实例方法?

How to call any instance method in ruby object without instantiating it?

我正在创建一个辅助模块以在调用其方法之前初始化该对象

module Initialized
  extend ActiveSupport::Concern

  class_methods do
    def run(*args)
      new(*args).run
    end

    def call(*args)
      new(*args).call
    end

    def execute(*args)
      new(*args).create
    end
  end
end

所以我不需要在我的帮助模块中定义 runcallexecute,我需要接收任何方法名称并检查它是否存在于主 class 初始化后,如果主 class 中存在请求的 instance 方法,如果不存在则调用错误

我会说我的目标代码是这样的

module Initialized
  extend ActiveSupport::Concern
  class_methods do
    def _(*args, methodname)
      new(*args).try(:send, "#{methodname}") || raise 'Method not exist'
    end
  end
end

示例用法为

class MyClass
  include Initialized

  def initialize(param1)
    @param1 = param1
  end

  def call
    puts "call '#{@param1}'"
  end
end

然后打电话

MyClass.call('method param')

我找到了这些链接,但还找不到我的答案:

meta-dynamic-generic-programming-in-ruby

我找到了更好的解决方案而不是使用模块, 我可以使用 class 方法 self.method_missing

def self.method_missing(method_name, *args, &block)
  obj = new(*args)
  raise NoMethodError, "undefined method `#{method_name}' for #{self}:Class" unless obj.respond_to?(method_name)
  obj.send(method_name, &block)
end

但限制是我必须将它复制到每个 class 每当我需要使用此功能时

尽管 method_missing 可以完成这项工作,但在这种情况下我可能会避免使用它,而倾向于更明确的授权。简单而肮脏的例子:

module InstanceDelegator
  def delegate_to_instance(*methods)
    methods.each do |method_name|
      define_singleton_method method_name do |*args|
        new(*args).public_send(method_name)
      end
    end
  end
end

class Foo
  extend InstanceDelegator

  delegate_to_instance :bar # <- define explicitly which instance methods
                            # should be mirrored by the class ones

  def bar
    puts "bar is called"
  end

  def baz
    puts "baz is called"
  end
end

# and then

Foo.bar #  => bar is called
Foo.baz # NoMethodError ...

# reopening works too
class Foo
  delegate_to_instance :baz
end

Foo.baz # baz is called

优点:

  1. 您不需要重新定义 method_missing(减少魔法 -> 减少调试代码时的痛苦)
  2. 您可以精确控制要使用 class 级别“shorthand”包装哪些实例方法(委托您不想要的东西的机会更少 - 更健壮的代码)
  3. (次要)无需显式引发 NoMethodError - 您可以完全依赖核心调度...