在Mixins中初始化实例变量

Joh*_*ter 11 ruby mixins

是否有任何干净的方法来初始化模块中的实例变量以用作Mixin?例如,我有以下内容:

module Example

  def on(...)   
    @handlers ||= {} 
    # do something with @handlers
  end

  def all(...)
    @all_handlers ||= []
    # do something with @all_handlers
  end

  def unhandled(...)
    @unhandled ||= []
    # do something with unhandled
  end

  def do_something(..)
    @handlers     ||= {}
    @unhandled    ||= []
    @all_handlers ||= []

    # potentially do something with any of the 3 above
  end

end
Run Code Online (Sandbox Code Playgroud)

请注意,我必须反复检查@member每个功能是否已在每个功能中正确初始化 - 这有点刺激性.我宁愿写:

module Example

  def initialize
    @handlers     = {}
    @unhandled    = []
    @all_handlers = []
  end

  # or
  @handlers  = {}
  @unhandled = []
  # ...
end
Run Code Online (Sandbox Code Playgroud)

而不必重复确保事情正确初始化.但是,据我所知,这是不可能的.除了在扩展类中添加initialize_me方法Example和调用之外,还有什么方法initialize_me吗?我确实看到了这个例子,但是Class为了实现这个目标,我无法将其修补.

Mor*_*ori 13

module Example
  def self.included(base)
    base.instance_variable_set :@example_ivar, :foo
  end
end
Run Code Online (Sandbox Code Playgroud)

编辑:请注意,这是设置类实例变量.当模块混合到类中时,无法创建实例上的实例变量,因为尚未创建这些实例.但是,您可以在mixin中创建初始化方法,例如:

module Example
  def self.included(base)
    base.class_exec do
      def initialize
        @example_ivar = :foo
      end
    end
  end
end
Run Code Online (Sandbox Code Playgroud)

在调用包含类的初始化方法(任何人?)时,可能有一种方法可以做到这一点.不确定.但这是另一种选择:

class Foo
  include Example

  def initialize
    @foo = :bar
    after_initialize
  end
end

module Example
  def after_initialize
    @example_ivar = :foo
  end
end
Run Code Online (Sandbox Code Playgroud)