【问题标题】:Inject new method calls in a existing method inside a class在类中的现有方法中注入新方法调用
【发布时间】:2021-05-25 17:36:10
【问题描述】:

在 ruby​​ 中,我们可以向当前类实例注入新方法

Class A
  def something
     pp "something"
  end
end

A.class_eval do
  def another_thing
    pp "another thing"
  end
end

但是有办法在现有方法中“注入”新方法调用吗?

例子:

重写后的东西他一直在打电话

pp "something"

但现在拨打另一个电话,例如:

pp 1 + 1

所以结果是

def something
 pp "something"
 pp 1 + 2
end

【问题讨论】:

  • @SergioTulentsev 但是您可以获取对原始方法的引用并在替换的开头或结尾调用原始方法。所以你可以在方法的开头或结尾注入代码。
  • @muistooshort:是的,这就是我的“装饰/包装方法”所暗示的。
  • 你说“阻止调用”,但看不到一个块(当然不包括class_eval 的那个)
  • @SergioTulentsev,当然可以。我一直都这样做。假设类是A,方法是符号m。然后A.instance_method(m).source_location 为您提供包含该方法的源代码和它开始的行的文件。只需解析文本,插入所需的代码,eval 结果字符串和Bob's your uncle。顺便说一句,那是你照片背景中费城的白色沙滩之一吗?
  • @SergioTulentsev 对不起,我已经修复了我放置“块”的位置

标签: ruby-on-rails ruby sinatra


【解决方案1】:

你能神奇地将一行代码注入现有方法的任意位置吗?不。至少,我什至不敢尝试一些疯狂的黑魔法诡计。

你能用一个块注入行为吗?是的(尽管我不确定这是否真的是您要问的,因为您的代码 sn-ps 都不包含单个块)。为此,原始方法必须指定yield 的位置。例如:

A.class_eval do
  def another_thing
    pp "another thing"
    yield if block_given?
  end
end

a = A.new
# Invoke the "original" behaviour"
a.another_thing
# Inject your "new" behaviour at the end
a.another_thing { pp 1 + 2 }

您能否在仍调用原始行为的同时覆盖方法?是的,这可以使用Module.prepend

module ThingOverrider
  def another_thing
    super
    pp 1 + 2
  end
end

A.prepend(ThingOverrider)

使用super 可以让您灵活地选择where 来调用原始实现,但是,这不允许您将功能任意注入原始方法的中间。

【讨论】:

  • 对不起,我已经修复了我放置“块”的位置
  • 这能回答你的问题吗?我仍然不能 100% 确定您所说的“在现有方法中注入新调用”是什么意思,但这种技术至少可以用于实现您给出的示例。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-12-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多