Initializing instance variables in Mixins

后端 未结 4 854
情话喂你
情话喂你 2021-02-05 21:41

Is there any clean way to initialize instance variables in a Module intended to be used as Mixin? For example, I have the following:

module Example

  def on(..         


        
相关标签:
4条回答
  • 2021-02-05 22:08

    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.

    0 讨论(0)
  • 2021-02-05 22:09
    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
    
    0 讨论(0)
  • 2021-02-05 22:15

    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=[]>
    
    0 讨论(0)
  • 2021-02-05 22:22

    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.

    0 讨论(0)
提交回复
热议问题