动态扩展ruby中的现有方法或重写send方法
假设我们有A、B、C班动态扩展ruby中的现有方法或重写send方法,ruby,metaprogramming,Ruby,Metaprogramming,假设我们有A、B、C班 A def self.inherited(sub) # meta programming goes here # take class that has just inherited class A # and for foo classes inject prepare_foo() as # first line of method then run rest of the code end def prepare_foo # =
A
def self.inherited(sub)
# meta programming goes here
# take class that has just inherited class A
# and for foo classes inject prepare_foo() as
# first line of method then run rest of the code
end
def prepare_foo
# => prepare_foo() needed here
# some code
end
end
B < A
def foo
# some code
end
end
C < A
def foo
# => prepare_foo() needed here
# some code
end
end
A
def自我继承(sub)
#这里是元编程
#以刚继承了类A的类为例
#对于foo类,将prepare_foo()作为
#方法的第一行,然后运行其余代码
结束
def准备好了吗
#=>此处需要准备_foo()
#一些代码
结束
结束
B此处需要准备_foo()
#一些代码
结束
结束
正如您所看到的,我正在尝试将foo\u prepare()
调用注入到每个foo()
方法中
如何做到这一点
另外,我一直在考虑在class A
中重写send
类,这样我就可以运行foo\u prepare
,而不是让send
(super)来完成该方法的其余部分
你们认为,解决这个问题的最佳方法是什么?这里有一个解决方案。虽然它基于模块包含,而不是从类继承,但我希望您仍然会发现它很有用
module Parent
def self.included(child)
child.class_eval do
def prepare_for_work
puts "preparing to do some work"
end
# back up method's name
alias_method :old_work, :work
# replace the old method with a new version, which has 'prepare' injected
def work
prepare_for_work
old_work
end
end
end
end
class FirstChild
def work
puts "doing some work"
end
include Parent # include in the end of class, so that work method is already defined.
end
fc = FirstChild.new
fc.work
# >> preparing to do some work
# >> doing some work
我推荐解决方案(已被接受)。以下是我所做的符合我需要的事情
class A
def send(symbol,*args)
# use array in case you want to extend method covrage
prepare_foo() if [:foo].include? symbol
__send__(symbol,*args)
end
end
或
从Ruby 2.0开始,您可以使用“prepend”简化Sergio的解决方案:
module Parent
def work
puts "preparing to do some work"
super
end
end
class FirstChild
prepend Parent
def work
puts "doing some work"
end
end
fc = FirstChild.new
fc.work
这允许模块重写类的方法,而不需要alias_方法。非常感谢非常干净的oop解决方案。我使用了更简单的修复方法,但我将大胆地在未来记住这一点。
module Parent
def work
puts "preparing to do some work"
super
end
end
class FirstChild
prepend Parent
def work
puts "doing some work"
end
end
fc = FirstChild.new
fc.work