Ruby 包含任何模块时的回调
Ruby callback when any module is included
我知道我们可以为任何单独的模块定义 included
回调。
有什么方法可以定义每当 任何 模块被包含在另一个模块或 class 中时调用的回调?然后回调最好可以访问包含的模块和包含它的 class/module。
我无法思考或找到 Ruby 中的内置方法来做到这一点。
一种替代方法是直接对 Module
class 进行猴子修补以创建回调。为此,我们可以在原始方法 include
和 extend
周围添加一些包装器方法,以在每次调用 include
或 extend
方法时强制执行我们定义的回调。
以下几行内容应该有效:
class Module
def self.before
m_include = instance_method(:include)
m_extend = instance_method(:extend)
define_method(:include) do |*args, &block|
included_callback(args[0])
m_include.bind(self).call(*args, &block)
end
define_method(:extend) do |*args, &block|
extend_callback(args[0])
m_extend.bind(self).call(*args, &block)
end
end
def included_callback(mod_name)
puts "#{self} now has included Module #{mod_name}"
end
def extend_callback(mod_name)
puts "#{self} now has extended Module #{mod_name}"
end
before
end
一个测试它是否有效的例子:
module Awesome
def bar
puts "bar"
end
def self.baz
puts "baz"
end
end
class TestIncludeAwesome
include Awesome
end
class TestExtendAwesome
extend Awesome
end
示例代码应输出以下内容:
> TestIncludeAwesome now has included Module Awesome
> TestExtendAwesome now has extended Module Awesome
class D
def self.callback(mod)
include mod
end
end
module M
def hello
puts 'hi'
end
def self.included(klass)
D.callback(self) unless klass == D
end
end
class C
include M
end
C.new.hello #=> 'hi'
D.new.hello #=> 'hi'
当C
包含M
时,M::included
与klass#=>C
一起执行。由于 klass == D
是 false
,因此执行 D.callback(M)
。 callback
在classD
中包含M
,然后M::included
与klass#=>D
一起执行。由于 klass == D
现在为真,因此 M
不会再次包含在 D
中。
我知道我们可以为任何单独的模块定义 included
回调。
有什么方法可以定义每当 任何 模块被包含在另一个模块或 class 中时调用的回调?然后回调最好可以访问包含的模块和包含它的 class/module。
我无法思考或找到 Ruby 中的内置方法来做到这一点。
一种替代方法是直接对 Module
class 进行猴子修补以创建回调。为此,我们可以在原始方法 include
和 extend
周围添加一些包装器方法,以在每次调用 include
或 extend
方法时强制执行我们定义的回调。
以下几行内容应该有效:
class Module
def self.before
m_include = instance_method(:include)
m_extend = instance_method(:extend)
define_method(:include) do |*args, &block|
included_callback(args[0])
m_include.bind(self).call(*args, &block)
end
define_method(:extend) do |*args, &block|
extend_callback(args[0])
m_extend.bind(self).call(*args, &block)
end
end
def included_callback(mod_name)
puts "#{self} now has included Module #{mod_name}"
end
def extend_callback(mod_name)
puts "#{self} now has extended Module #{mod_name}"
end
before
end
一个测试它是否有效的例子:
module Awesome
def bar
puts "bar"
end
def self.baz
puts "baz"
end
end
class TestIncludeAwesome
include Awesome
end
class TestExtendAwesome
extend Awesome
end
示例代码应输出以下内容:
> TestIncludeAwesome now has included Module Awesome
> TestExtendAwesome now has extended Module Awesome
class D
def self.callback(mod)
include mod
end
end
module M
def hello
puts 'hi'
end
def self.included(klass)
D.callback(self) unless klass == D
end
end
class C
include M
end
C.new.hello #=> 'hi'
D.new.hello #=> 'hi'
当C
包含M
时,M::included
与klass#=>C
一起执行。由于 klass == D
是 false
,因此执行 D.callback(M)
。 callback
在classD
中包含M
,然后M::included
与klass#=>D
一起执行。由于 klass == D
现在为真,因此 M
不会再次包含在 D
中。