假设我们有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
# => 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
正如您所看到的,我正在尝试为每个foo_prepare()
方法注入foo()
次调用。
怎么办呢?
此外,我一直在考虑以send
覆盖class A
类,以便运行foo_prepare
,而不是让send
(超级)来完成其余方法
你们怎么想?解决这个问题的最佳方法是什么?
答案 0 :(得分:7)
这是适合您的解决方案。虽然它基于模块包含而不是从类继承,但我希望你仍然会发现它很有用。
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
答案 1 :(得分:4)
我推荐Sergio's解决方案(已接受)。这是我做的,符合我的需要。
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
或
class A
alias_method :super_send, :send
def send(symbol,*args)
prepare_foo() if [:foo].include? symbol
super_send(symbol,*args)
end
end
答案 2 :(得分:2)
从Ruby 2.0开始,你可以使用&#39; prepend&#39;简化塞尔吉奥的解决方案:
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_method。