【问题标题】:Calling original method from a redefined one从重新定义的方法调用原始方法
【发布时间】:2016-12-04 18:12:40
【问题描述】:

我的问题基于answer to the topic “redefining a single ruby method on a single instance with a lambda”

如何重新定义方法并在新方法中调用原始定义? some_object 类的其他实例不应受到影响。

def some_object.some_method
  # call original `some_object.some_method` here
  do_something_else
end

【问题讨论】:

  • @AndrewPiliser 我以前见过这个问题,但据我了解,它是关于重新定义特定类的所有实例的方法,而我的问题是关于在不触及任何行为的情况下重新定义特定对象的方法其他物体。我已经更改了我的问题以使其更清楚。
  • 没有单例方法。 Ruby 中的每个方法都是实例方法。你所说的“单例方法”只是单例类的一个实例方法。 Ruby 中的每个方法都是类中的实例方法,因此没有什么特别之处,问题完全适用。 (我并不是说因为我的答案是公认的答案,所以我不在乎代表。)一旦你理解了这一点,Ruby 突然变得很多简单了。跨度>
  • @JörgWMittag Your answer on the other question 很棒但非常广泛——非常适合博客文章。我觉得我的问题与上面链接的问题不同,因为它是一种开放的解释(红宝石示例似乎无效:Foo 定义了两次,尚不清楚他是要解释继承还是更改Foo 实例(全部/其中一个?)在运行时。考虑到该问题的表述有多模糊,您的回答实际上确实是公正的。

标签: ruby monkeypatching


【解决方案1】:

如果some_object.some_method 不是单例方法,那么您可以在重新定义的方法中调用super

def some_object.some_method
  super
  do_something_else
end

如果some_object.some_method是单例方法,那么

红宝石 >= 2.0.0

您可以在模块中定义该方法

module SomeModule
  def some_method
    super
    do_something_else
  end
end

然后将其添加到对象的单例类

some_object.singleton_class.prepend(SomeModule)

红宝石

你必须创建一个别名然后重新定义,因为没有Module#prepend

class << some_object  # open the singleton class of some_object
  alias some_method_original some_method

  def some_method
    some_method_original
    do_something_else
  end
end

【讨论】:

【解决方案2】:
class Klass
  def greeting
    puts "hiya"
  end

  def add_personal_greeting(str)
    define_singleton_method(:greeting) do
      super
      puts str
    end  
  end
end

Bob 得到一个句柄并尝试标准问候语。

bob = Klass.new
  #=> #<Klass:0x007fa66b084ad0> 
bob.greeting
  # hiya

他觉得这太没有人情味了,所以他决定在问候之后加上“我是鲍勃”。他通过在他的单例类上定义一个方法greeting 来实现这一点,该方法调用Klass 的实例方法greeting,然后在问候语中添加另一行。

bob.add_personal_greeting("I'm Bob")

他试了一下。

bob.greeting
  # hiya
  # I'm Bob

好多了。注意

bob.singleton_class.superclass
  #=> Klass

与此同时,露西尝试了标准问候语。

lucy = Klass.new
  #=> #<Klass:0x007fa66a9ed050> 
lucy.greeting
  # hiya

她对此并不疯狂,但它会做到的。

Bob 决定改变他的问候方式。

bob.add_personal_greeting("I'm Robert")

试一试。

bob.greeting
  # hiya
  # I'm Robert

【讨论】:

  • add_personal_greetingdefine_singleton_method 的有趣方法。但是如果我只知道some_object 的接口,或者如果我无法控制它的类(例如它来自我使用的某个库),那么这种方法不适用,对吧?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-15
  • 1970-01-01
  • 2010-09-22
  • 1970-01-01
  • 2013-05-16
  • 1970-01-01
相关资源
最近更新 更多