Une autre alternative est d'utiliser des méthodes non liées:
class A
original_test = instance_method(:test)
define_method(:test) do
puts "Log Message!"
original_test.bind(self).call
end
end
class A
original_test = instance_method(:test)
counter = 0
define_method(:test) do
counter += 1
puts "Counter = #{counter}"
original_test.bind(self).call
end
end
irb> A.new.test
Counter = 1
Log Message!
#=> #....
irb> A.new.test
Counter = 2
Log Message!
#=> #.....
Ceci a l'avantage qu'il ne pollue pas l'espace de noms avec des noms de méthode supplémentaires, et est assez facilement Abstraite, si vous souhaitez effectuer une méthode de classe add_logging
ou ce que vous avez.
class Module
def add_logging(*method_names)
method_names.each do |method_name|
original_method = instance_method(method_name)
define_method(method_name) do |*args,&blk|
puts "logging #{method_name}"
original_method.bind(self).call(*args,&blk)
end
end
end
end
class A
add_logging :test
end
Ou, si vous voulez être en mesure de faire un tas d'aspects w/o beaucoup de la plaque de la chaudière, vous pouvez écrire une méthode qui écrit des méthodes d'aspect en ajoutant!
class Module
def self.define_aspect(aspect_name, &definition)
define_method(:"add_#{aspect_name}") do |*method_names|
method_names.each do |method_name|
original_method = instance_method(method_name)
define_method(method_name, &(definition[method_name, original_method]))
end
end
end
# make an add_logging method
define_aspect :logging do |method_name, original_method|
lambda do |*args, &blk|
puts "Logging #{method_name}"
original_method.bind(self).call(*args, &blk)
end
end
# make an add_counting method
global_counter = 0
define_aspect :counting do |method_name, original_method|
local_counter = 0
lambda do |*args, &blk|
global_counter += 1
local_counter += 1
puts "Counters: [email protected]#{global_counter}, [email protected]#{local_counter}"
original_method.bind(self).call(*args, &blk)
end
end
end
class A
def test
puts "I'm Doing something..."
end
def test1
puts "I'm Doing something once..."
end
def test2
puts "I'm Doing something twice..."
puts "I'm Doing something twice..."
end
def test3
puts "I'm Doing something thrice..."
puts "I'm Doing something thrice..."
puts "I'm Doing something thrice..."
end
def other_tests
puts "I'm Doing something else..."
end
add_logging :test, :test2, :test3
add_counting :other_tests, :test1, :test3
end
"Cela a l'avantage de ne pas polluer l'espace de noms avec des noms de méthodes supplémentaires": Oui! Et étant donné que cette pollution était la source du problème des PO en premier lieu, c'est un avantage plutôt convaincant. –
Parfait, merci –
Attendez ... Donc, ma classe d'origine doit écrire sa méthode comme non liée en premier lieu? C'est un peu ennuyeux –