【问题标题】:Copy method from one class to another将方法从一个类复制到另一个类
【发布时间】:2012-03-06 20:14:13
【问题描述】:

我想用一些方法编写小类,这些方法实际上属于其他类,那么如何在其他类中定义现有方法的副本。我相信这是我不懂的元编程魔术师。

class Foo
  def initialize
    # with blocks, I would just pass block, but this is methods
    # so this won't work
    Bar.class_eval(perform)
    Bar.class_eval(process)
    Bar.class_eval(save)
  end

  def perform
    1+1
  end

  def process
    # some code
  end

  def save
    # some code
  end
end

class Bar; end

foo = Foo.new
foo.perform
#=> 2
Bar.test
#=> 1

为什么我需要这个?我正在研究仅用三种方法上课的 gem。在初始化(将隐藏在父类中)时,它将将此方法传递给不同的类。我可以用积木来做这个,但是用方法就更干净了。

PS:这就像将方法从一个类复制到另一个类

PSS:或者......如何将方法转换为proc,所以我可以将它传递给class_eval

【问题讨论】:

  • 也许你必须使用委托? khelll.com/blog/ruby/delegation-in-ruby
  • 你不能只包含一个模块吗?
  • @Fivell,也许吧!我现在需要阅读有关委托的内容
  • 添加了示例链接
  • @Sergio Tulentsev 在这种情况下 - 否

标签: ruby metaprogramming proc


【解决方案1】:

要将方法转换为可以像 Proc 一样调用的东西,请使用 obj.method(:method_name)。这将为您提供一个绑定 Method 对象,当called 时,将在obj 上调用该对象。如果你想在同一个类的不同对象上调用它,你可以调用method.unbind.bind(different_obj)

这仍然不允许您将方法从一个类“复制”到另一个类。如果您想允许用户传递一个定义 3 个方法的类,而不是传递 3 个块,如果您在内部存储对该类(或其实例)的引用,并根据需要在其上调用方法,它可能会更好.这就是评论“委托”的人的意思。

或者,您可以让用户传递一个模块,并将您自己的类includeextend 设为模块(根据需要)。

【讨论】:

  • 我相信我会使用参考 :) 但现在我很感兴趣是否可以在 Ruby 中的类之间复制方法!
  • 我不认为有,但是如果您找到方法,请发布。我也想知道。
  • 我相信元编程可以做任何事情 :) 谢谢你的回答
【解决方案2】:

可以将方法从一个类复制到另一个类,但有一个主要警告:目标类必须是 kind_of?源类,或者源必须是模块。此限制部分记录在UnboundMethod#bind 的文档中,但要查看模块异常,您必须查看该方法的源代码。 This answer 包含有关该主题的更多讨论。

这是一个例子:

module A
  def say_hello
    puts "Hello"
  end
end

class B
  define_method(:say_hello, A.instance_method(:say_hello))
end

b = B.new
b.say_hello
=> Hello

如果A 是一个类并且B 是一个继承自A 的类,这也将起作用。但在这种情况下,您已经通过继承获得了该方法,所以我个人认为它没有用处。

我发现这种模式有用的一种情况是在设计 DSL 时使用继承自 BasicObject 的对象。由于BasicObject 不像Object 那样include Kernel,因此您无法轻松访问许多有用的方法,例如#instance_variables 甚至#class。但是您可以将它们从内核中单独复制到您的类中:

class Foo < BasicObject
  define_method(:class, ::Kernel.instance_method(:class))
end

f = Foo.new
puts f.class
=> Foo

【讨论】:

    猜你喜欢
    • 2021-03-25
    • 2010-11-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-03-18
    相关资源
    最近更新 更多