我正在使用gem,出于某种原因,在我的某些代码使用之前,需要对其中一个方法进行修补。
问题出在这里,我怎么能只为我的一些代码启用这个补丁呢。对于类中的某些方法,我需要启用此补丁;一些我想禁用这个补丁。
怎么做?
class FromGem
def BlahBlah
#patch here
end
end
class A
def Test1
#need patch
end
def Test2
# don't need patch
end
end
答案 0 :(得分:6)
这就是改进的目的。
说,我们有以下第三方代码:
class FromGem
def say_hello
'Hello'
end
end
FromGem.new.say_hello
# => 'Hello'
我们想把它扩展为说“Hello World”,我们会做这样的事情:
module ExtendFromGem
def say_hello
super + ' World'
end
end
class FromGem
prepend ExtendFromGem
end
FromGem.new.say_hello
# => 'Hello World'
这只是扩展行为的标准方式,当然,这仍然是全球性的。如果我们想限制我们的猴子补丁的范围,我们将需要使用优化:
module ExtendedFromGem
module ExtendFromGem
def say_hello
super + ' World'
end
end
refine FromGem do
prepend ExtendFromGem
end
end
FromGem.new.say_hello
# => 'Hello'
# We haven't activated our Refinement yet!
using ExtendedFromGem
FromGem.new.say_hello
# => 'Hello World'
# There it is!
现在,我们想要写的是:
class A
def test1
using ExtendedFromGem
FromGem.new.say_hello
end
def test2
FromGem.new.say_hello
end
end
A.new.test1
# => 'Hello World'
A.new.test2
# => 'Hello'
不幸的是,这不起作用:优化仅适用于脚本范围,在这种情况下,优化仅在调用using
后才能激活,或者它们在模块范围内工作,在在整个模块正文中它们是活动的,甚至在调用using
之前,所以我们可以做的是,这(IMO,这更清洁):
class A
using ExtendedFromGem
def test1
FromGem.new.say_hello
end
end
class A
def test2
FromGem.new.say_hello
end
end
A.new.test1
# => 'Hello World'
A.new.test2
# => 'Hello'
或者这个:
class A
def test2
FromGem.new.say_hello
end
end
using ExtendedFromGem
class A
def test1
FromGem.new.say_hello
end
end
A.new.test1
# => 'Hello World'
A.new.test2
# => 'Hello'
Etvoilà:test1
看到了细化,test2
没有。
答案 1 :(得分:1)
如果您想在一个地方更改行为,那么您不需要做任何事情,只需使用或不使用gem方法编写几行符合您要求的代码
如果您需要在多个位置修改行为,则创建一个实现已更改行为的方法。在这种情况下;你将使用适配器设计模式;
步骤进行:
尽量不要修改原始类;遵循开放式原则
class A
def Test1
# need patch
# you use GemAdapter rather than FromGem
end
def Test2
# don't need patch
# use FromGem class
end
def Test3
# need patch
# you use GemAdapter rather than FromGem
end
end
class GemAdapter
def new_behavior
gem_instance = FromGem.new
# implement your new behavior you desire
end
end
答案 2 :(得分:1)
这也可以是一个解决方案
class <<
用于修改特定实例;元编程的一部分
class A
def print
p 'Original method'
end
end
class B
def initialize
@new_instance_of_a = A.new
end
def my_method
modifiable_a = A.new
# modifying the instance of class A i.e. modifiable_a
class << modifiable_a
def print
p 'Monkey patch'
end
end
modifiable_a .print
end
def normal_method
@new_instance_of_a.print
end
end
然而,修改local_instance
并没有多大意义。如果这个修改过的实例可以在更多地方使用,那么使用这种方法是值得的