Initializing instance variables in Mixins

旧城冷巷雨未停 提交于 2019-12-03 03:32:52
module Example
  def self.included(base)
    base.instance_variable_set :@example_ivar, :foo
  end
end

Edit: Note that this is setting a class instance variable. Instance variables on the instance can't be created when the module is mixed into the class, since those instances haven't been created yet. You can, though, create an initialize method in the mixin, e.g.:

module Example
  def self.included(base)
    base.class_exec do
      def initialize
        @example_ivar = :foo
      end
    end
  end
end

There may be a way to do this while calling the including class's initialize method (anybody?). Not sure. But here's an alternative:

class Foo
  include Example

  def initialize
    @foo = :bar
    after_initialize
  end
end

module Example
  def after_initialize
    @example_ivar = :foo
  end
end

Perhaps this is a little hacky, but you can use prepend to get the desired behavior:

module Foo
  def initialize(*args)
    @instance_var = []
    super
  end
end

class A
  prepend Foo
end

Here is the output from the console:

2.1.1 :011 > A.new
 => #<A:0x00000101131788 @instance_var=[]>

modules provides hooks, as Module#included. I suggest you check out ruby doc on the topic, or use ActiveSupport::Concern, which provides some helpers on modules.

I think there may be a simpler answer to this. The module should have an initializer that initialises the variables as you normally would do. In the initializer for the class that includes the module, invoke super() to invoke the initializer in the included module. This is simply following the method dispatch rules in Ruby.

On reflection, this will not work so well if the class including the module also has a superclass that needs to be initialised. The initializer in the module would need to accept a variable parameter list and pass this up to the superclass. It looks like a good avenue to explore though.

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!