ruby 混合和继承注入
我需要在父类的每个子类中注入回调。因此,必须首先调用带有回调的方法,然后调用所有存在的链:
可以实现 alias_method (或 alias_method_chain):
module ChildMod1
def save
puts "save ChildMod1"
super
end
end
module ChildMod2
def save
puts "save ChildMod2"
super
end
end
class Parent
def save
puts "save Parent"
end
end
class Child < Parent
include ChildMod1
include ChildMod2
def save
puts "save Child"
super
end
alias_method :old_save, :save
module_eval <<-R
def save
puts "save Callback"
old_save
end
R
end
c = Child.new
c.save
输出
save Callback
save Child
save ChildMod2
save ChildMod1
save Parent
,但是是否可以通过继承来实现这一点?就像 ChildMod1 或 ChildMod2 中一样。我想在模块空间内执行代码以获得继承
module ChildMod1
def save
puts "save ChildMod1"
super
end
end
module ChildMod2
def save
puts "save ChildMod2"
super
end
end
class Parent
def save
puts "save Parent"
end
end
class Child < Parent
include ChildMod1
include ChildMod2
def save
puts "save Child"
super
end
module_eval <<-R
def save
puts "save Callback"
super
end
R
end
c = Child.new
c.save
输出
save Callback
save ChildMod2
save ChildMod1
save Parent
的所有好处,如您所见,它只是覆盖 Child
UPDATE wdebeaum 解决方案很好,但是如果我需要动态创建很多方法,认为 module_eval 或 Analog 并在类中重新定义它们怎么办?我无法为他们创建单独的模块。
class TestEval
def redefine_me
puts "Test method"
super # I expect that it will call Eval method, but module_eval just overwrite it
end
module_eval <<-R
def redefine_me
puts "Eval method"
end
R
end
更新2 使用单例类我会得到错误的链 Eval =>测试而不是测试 => Eval
class TestEval
def initialize
class << self
def redefine_me
puts "Eval method"
super
end
end
end
def redefine_me
puts "Test method"
end
end
TestEval.new.redefine_me
假设我有一个类方法“field”,它将一些实例方法添加到数据流(例如,它将添加 setter 和 getter 方法),并且我想重新定义其中一个方法,如下所示:
class Datastream
field :name
def name=(value)
puts "redefined!"
super
end
end
I need to inject a callbacks in every child class of a Parent class. So, method with callbacks must be called first, and all present chain later:
it is possible to achive thought alias_method (or alias_method_chain):
module ChildMod1
def save
puts "save ChildMod1"
super
end
end
module ChildMod2
def save
puts "save ChildMod2"
super
end
end
class Parent
def save
puts "save Parent"
end
end
class Child < Parent
include ChildMod1
include ChildMod2
def save
puts "save Child"
super
end
alias_method :old_save, :save
module_eval <<-R
def save
puts "save Callback"
old_save
end
R
end
c = Child.new
c.save
output
save Callback
save Child
save ChildMod2
save ChildMod1
save Parent
but is it possible to achieve this via inheritance? like in ChildMod1 or ChildMod2. I whant to execute a code inside a module space to get all benefits from inheritance
module ChildMod1
def save
puts "save ChildMod1"
super
end
end
module ChildMod2
def save
puts "save ChildMod2"
super
end
end
class Parent
def save
puts "save Parent"
end
end
class Child < Parent
include ChildMod1
include ChildMod2
def save
puts "save Child"
super
end
module_eval <<-R
def save
puts "save Callback"
super
end
R
end
c = Child.new
c.save
Output
save Callback
save ChildMod2
save ChildMod1
save Parent
as you see, it just overwrite Child
UPDATE
wdebeaum solution is good, but what if i need to create a lot of methods dynamically thought module_eval or analog and redefine them inside a class? I cannot create a separate module for them.
class TestEval
def redefine_me
puts "Test method"
super # I expect that it will call Eval method, but module_eval just overwrite it
end
module_eval <<-R
def redefine_me
puts "Eval method"
end
R
end
UPDATE2
using a singleton class i'll got wrong chain Eval => Test instead of Test => Eval
class TestEval
def initialize
class << self
def redefine_me
puts "Eval method"
super
end
end
end
def redefine_me
puts "Test method"
end
end
TestEval.new.redefine_me
Let assume, that I have a class method "field", that add some instance methods to a Datastream (for ex it'll add setter and getter methods) and I whant to redefine one of this methods, like this:
class Datastream
field :name
def name=(value)
puts "redefined!"
super
end
end
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
您可以将回调方法放入其自己的模块中,并重写父级的初始化方法以
扩展
该模块(如果需要,使用alias_method
)。这会将回调方法放在 Child 的方法之前,方法是将其链接到每个 Child 实例的单例类。只需从第二个代码示例中删除module_eval
部分,并将其添加到c = Child.new
之前:输出:
You could put the callback method in its own module, and rewrite the Parent's initialize method to
extend
that module (usingalias_method
if necessary). This will put the callback method before the Child's method, by linking it to each Child instance's singleton class. Just remove themodule_eval
part from your second code example, and add this beforec = Child.new
:Output: