10

Ruby では、クラスに一連のモジュールを含め、そのクラスを初期化するときに、これらの個々のモジュールでブロックまたはメソッドを実行する (または単にインスタンス変数を編集する方法を見つける) ようにします。モジュールでメソッドを作成し、クラスの初期化メソッドで呼び出すことでこれを実行できることはわかっていますが、モジュールを含めて1つのメソッドを呼び出して、モジュールが初期化するために追加するコードを実行するだけでこれを行う方法が必要です、そうすれば、含まれるすべてのモジュールの初期化メソッドにコード行を追加することを心配することなく、クラスに大量のものを含めることができます。エイリアシング、スーパー、および関連するものをチェックアウトしましたが、何も得られませんでした...達成したいことを理解するのに役立つ場合は、ここにいくつかの擬似コードがあります:

module Mod1  
    call_this_block_on_initialize { @a.push 4 }  
end  

module Mod2  
    call_this_block_on_initialize { @a.push 5 }  
end  

class Test  
    attr_accessor :a  
    include Mod1  
    include Mod2  

    def initialize  
      @a = [1, 2, 3]  
      call_those_blocks_set_by_mods  
    end  
end  

t = Test.new
t.a # returns [1, 2, 3, 4, 5]

これは少し冗長かもしれませんが、タイトルは私がやろうとしていることを要約していると思います. 助けてくれてありがとう!

4

1 に答える 1

11

これを行うにはいくつかの方法があります。この例では、initialize メソッドを再定義し、必要なコードを追加します。

module MyModule
  def self.included(base) # built-in Ruby hook for modules
    base.class_eval do    
      original_method = instance_method(:initialize)
      define_method(:initialize) do |*args, &block|
        original_method.bind(self).call(*args, &block)
        @a.push 4 # (your module code here)
      end
    end
  end
end

class Test  
  attr_accessor :a  

  def initialize  
    @a = [1, 2, 3]    
  end  

  # It must be included after the `initialize` 
  # definition or the module won't find the method:
  include MyModule
end  

しかし:あなたが本当に欲しいのはサブクラス化だと思います。似たような動作をするクラスがたくさんあるように見える場合は、自然な抽象親クラスがあるかどうかを自問してください。super何をしたのか、なぜうまくいかなかったのか説明できますか?

于 2012-11-06T19:39:05.867 に答える