我知道我们可以为任何单个模块定义included
回调。
有没有办法定义每当任何模块包含在另一个模块或类中时调用的回调?然后,回调最好能够访问包含的模块和包含它的类/模块。
答案 0 :(得分:3)
我无法在Ruby中思考或找到内置的方法来实现它。
另一种方法是直接修补Module
类以创建回调。为此,我们可以在原始方法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
答案 1 :(得分:0)
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
在M
课程中包含D
,然后M::included
执行klass#=>D
。由于klass == D
现在为真,M
第二次未包含在D
中。