私は、initialize
の動作をモジュールからどのように拡張するかを考えようとしています。混じっているクラスのinitialize
にsuperを呼ぶことなくやりたい。私は呼び出しの通常のパターンをサポートしたいinclude
私はそれを把握することはできません。私はこの問題について見つけ出すことのできるものすべてを読んだことがあります。人々には提案がありますが、実際には(少なくとも私の手の中では)どちらも動作していないようです。ここでRubyモジュールで#initializeをオーバーライドすることはできますか?
は私が私が知っている(と思う)です:
- をそれがすべてで行うことができれば、それは
include
(すなわちModule.included(base)
)のフックを使用して行う必要があります。 include
フックは、包含クラスがinitialize
を定義する前に実行されるため、initialize
をbase.instance_eval
で定義しようとするだけで上書きされることはありません。method_added
フックを使用し、そこで対処することを提案しました。これは私が今試していることですが、フックがメソッド定義の始めに実行されるように見えますので、以下で見ているものになります。module Mo def self.included(klass) klass.instance_eval do def method_added(method) puts "Starting creation of #{method} for #{self.name}" case method when :initialize alias_method :original_initialize, :initialize puts "About to define initialize in Mo" def initialize original_initialize puts "Hello from Mo#initialize" end puts "Finished defining initialize in Mo" end puts "Finishing creation of #{method} for #{self.name}" end end end end class Foo include Mo def initialize puts "Hello from Foo#initialize" end end foo = Foo.new
これは、次の出力が生成されます。
Starting creation of initialize for Foo
Starting creation of original_initialize for Foo
Finishing creation of original_initialize for Foo
About to define initialize in Mo
Finished defining initialize in Mo
Finishing creation of initialize for Foo
Hello from Foo#initialize
Fooクラスからinitialize
はまだモジュールからの定義を上書きしているようですが、私には見えます。私は、これは、定義がまだ開いていることを推測しています。最後にどのブロックが開始され、最後に終了するかは問題ではないことを示唆しています。
誰かが実際にこれを行う方法を知っていて、それを働かせてくれたら、私を啓発してください。
FWIW、はい、私はこれをやりたがっている理由があると思います。
質問をした直後に 'prepend'を発見しました。私はそれが好きです! 1.9でそれを行う方法があるかどうか不思議です* – Huliax
単純に 'klass.prepend'の代わりに' klass.send:prepend'を使用することで何かが分かりませんか? – NobodysNightmare