我一直在尝试找出如何从模块扩展initialize
的行为。我想做到这一点而无需在要混入的类的initialize
中调用super。我想支持调用include
的正常模式,但无法弄清楚。我已经阅读了有关此事的所有内容,尽管人们有建议,但实际上却没有一个建议(至少在我手中)。
这是我(认为)我所知道的:
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,是的,我想我有充分的理由要这样做。
我一直在尝试找出如何从模块扩展初始化行为。我想做到这一点而无需在正在混合的类的initialize中调用super。我想支持...
[如果您使用的是Ruby 2.0或更高版本,则可以只使用prepend
。要求用户使用prepend
而不是include
,或执行以下操作:
好吧,在Ruby 1.9中,您可以向new
类方法中添加功能...
[如果使用Rails
在Foo的Initialize中有条件调用仅在存在的情况下才调用它会满足吗?