包含任何模块时的Ruby回调

时间:2017-03-28 16:54:29

标签: ruby module callback mixins

我知道我们可以为任何单个模块定义included回调。

有没有办法定义每当任何模块包含在另一个模块或类中时调用的回调?然后,回调最好能够访问包含的模块和包含它的类/模块。

2 个答案:

答案 0 :(得分:3)

我无法在Ruby中思考或找到内置的方法来实现它。

另一种方法是直接修补Module类以创建回调。为此,我们可以在原始方法includeextend周围添加一些包装器方法,以便在每次调用includeextend方法时强制执行定义的回调。

以下几行应该有效:

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 == Dfalse,因此执行D.callback(M)callbackM课程中包含D,然后M::included执行klass#=>D。由于klass == D现在为真,M第二次未包含在D中。