你有時可以把紅寶石推到espressso杯子裏。讓我們看看如何。
這裏有一個模塊FunNotFun ...
module FunNotFun
def fun
@method_type = 'fun'
end
def notfun
@method_type = 'not fun'
end
def method_added(id)
return unless @method_type
return if @bypass_method_added_hook
orig_method = instance_method(id)
@bypass_method_added_hook = true
method_type = @method_type
define_method(id) do |*args|
orig_method.bind(self).call(*args).tap do
puts "That was #{method_type}"
end
end
@bypass_method_added_hook = false
end
end
...你可以用它來擴展類...
class Thing
extend FunNotFun
fun
def f1
puts "hey"
end
notfun
def f2
puts "hey"
end
end
...這個結果:
Thing.new.f1
# => hey
# => That was fun
Thing.new.f2
# => hey
# => That was not fun
但請參閱下面的線路更好的方法。
註釋(見normalocity的答案)是少一些麻煩,並且,是一種常見的Ruby成語,會溝通更方便你的代碼的意圖。以下是如何與註解做到這一點:
module FunNotFun
def fun(method_id)
wrap_method(method_id, "fun")
end
def notfun(method_id)
wrap_method(method_id, "not fun")
end
def wrap_method(method_id, type_of_method)
orig_method = instance_method(method_id)
define_method(method_id) do |*args|
orig_method.bind(self).call(*args).tap do
puts "That was #{type_of_method}"
end
end
end
end
在使用時,註釋來定義的方法之後,而不是之前:
class Thing
extend FunNotFun
def f1
puts "hey"
end
fun :f1
def f2
puts "hey"
end
notfun :f2
end
的結果是一樣的:
Thing.new.f1
# => hey
# => That was fun
Thing.new.f2
# => hey
# => That was not fun
啊,這是我想到的更多 –
是第一種線程安全的方法嗎? –
@Semyon,如果您有多個線程同時向同一個類添加方法,請不要。但是幾乎總是隻通過一個線程添加方法。 –