0

先介绍一下上下文

我有一个Phone定义这样的方法的advertise类:

class Phone
  def advertise(phone_call)
    'ringtone'
  end
end

我想对这种方法进行一些修改。例如,当用户处于安静的环境中时,手机应该振动而不是响铃。为此,我定义了类似的模块

module DiscreetPhone    
  def advertise_quietly (phone_call)
    'vibrator'
  end
end

然后我的程序可以做

# add the module to the class so that we can redefine the method
Phone.include(DiscreetPhone) 
# redefine the method with its adaptation
Phone.send(:define_method, :advertise, DiscreetPhone.instance_method(:advertise_quietly ))

当然,对于这个例子,我硬编码了类和模块的名称,但它们应该是函数的参数。

因此,执行示例将给出:

phone = Phone.new
phone.advertise(a_call) # -> 'ringtone'
# do some adaptation stuff to redefine the method
...
phone.advertise(a_call) # -> 'vibrator'

终于来回答我的问题了

我想要一个调用原始函数并在其结果中附加一些内容的改编。我想这样写

module ScreeningPhone
  def advertise_with_screening (phone_call)
    proceed + ' with screening'
  end
end

但我不知道proceed调用应该做什么,甚至我应该在哪里定义它。

  • 我在 Windows 上使用 Ruby 2.3.0。
  • proceed可以用其他东西代替,但我想在定义适应的模块中尽可能保持干净。
4

2 回答 2

1

您可以通过预先添加模块而不是包含它来做到这一点。

而不是define_method用作一种 ersatz ,只需在您的模块中alias_method调用该方法。advertise

在您的advertise方法中,您可以调用super来调用继承层次结构。

于 2016-05-08T16:45:42.547 回答
0

在我看来,这种方法太复杂了,并且不恰当地使用Modules.

我建议考虑一种更简单的方法来实现这一点。

一种简单的方法是在 Phone 类中包含所有方法。

或者,您可以使用哈希作为环策略的查找表:

class Phone

    attr_accessor :ring_strategy

    RING_STRATEGIES = {
        ringtone:  -> { ring_with_tone },
        discreet:  -> { ring_quietly },
        screening: -> { ring_with_tone; ring_screening_too }
        # ...
    }

    def initialize(ring_strategy = :ringtone)
        @ring_strategy = ring_strategy
    end

    def ring
        RING_STRATEGIES[:ring_strategy].()
    end

end
于 2016-05-08T14:51:18.673 回答