Я хочу сделать метод рычага, который называют каждый раз, любая функция класса вызвана. Я попробовал method_added, но он выполняется только однажды во время определения класса,
class Base
def self.method_added(name)
p "#{name.to_s.capitalize} Method's been called!!"
end
def a
p "a called."
end
def b
p "b called."
end
end
t1 = Base.new
t1.a
t1.b
t1.a
t1.b
Output:
"A Method's been called!!"
"B Method's been called!!"
"a called."
"b called."
"a called."
"b called."
но мое требование - то, что любая функция класса, который называют где угодно в программе, инициировала "method_called", метод рычага.
Expected Output:
"A Method's been called!!"
"a called."
"B Method's been called!!"
"b called."
"A Method's been called!!"
"a called."
"B Method's been called!!"
"b called."
Если существует какой-либо определенный существующий метод рычага, который работает все равно, то скажите об этом.
Заранее спасибо..
Взгляните на Ядро # set_trace_func
. Он позволяет вам указать процедуру, которая вызывается всякий раз, когда происходит событие (например, вызов метода). Вот пример:
class Base
def a
puts "in method a"
end
def b
puts "in method b"
end
end
set_trace_func proc { |event, file, line, id, binding, classname|
# only interested in events of type 'call' (Ruby method calls)
# see the docs for set_trace_func for other supported event types
puts "#{classname} #{id} called" if event == 'call'
}
b = Base.new
b.a
b.b
Вывод:
Base a called
in method a
Base b called
in method b
method_added
служит для запуска кода, когда в класс добавлен новый метод; он не сообщает, когда метод был вызван. (Как вы обнаружили.)
Если вы не хотите следовать ответу mikej, вот класс, реализующий вашу спецификацию:
#!/usr/bin/ruby
class Base
def self.method_added(name)
if /hook/.match(name.to_s) or method_defined?("#{name}_without_hook")
return
end
hook = "def #{name}_hook\n p 'Method #{name} has been called'\n #{name}_without_hook\nend"
self.class_eval(hook)
a1 = "alias #{name}_without_hook #{name}"
self.class_eval(a1)
a2 = "alias #{name} #{name}_hook"
self.class_eval(a2)
end
def a
p "a called."
end
def b
p "b called."
end
end
t1 = Base.new
t1.a
t1.b
t1.a
t1.b
И вывод:
$ ./meta.rb
"Method a has been called"
"a called."
"Method b has been called"
"b called."
"Method a has been called"
"a called."
"Method b has been called"
"b called."