s2t*_*2t2 1 ruby inheritance metaprogramming
在Ruby中,是否可以从超类方法转换为子类方法而又不影响子类中的代码?我试图避免super在子类中调用。
class SuperClass
def do_something
puts "getting ready..."
# how to then yield back to the subclass do_something method?
puts "done."
end
end
class SubClass < SuperClass
def do_something
# how to first execute the superclass do_something method?
puts "doing something ..."
end
end
Run Code Online (Sandbox Code Playgroud)
所需的功能是专门调用SubClass.do_something并接收以下输出:
“准备...”
“做某事...”
“做完了。”
编辑:
也许真正的问题是:如何干涸下面的代码,删除对来电self.get_ready和self.finish_up所有子类,使用任何红宝石的元编程技术,保持这些类DRY:
class SuperClass
def self.get_ready
puts "getting ready ..."
end
def self.finish_up
puts "done."
end
end
class SubClassA < SuperClass
def self.do_something
self.get_ready
puts "doing something ..."
self.finish_up
end
end
class SubClassB < SuperClass
def self.do_something
self.get_ready
puts "doing something else, a little differently..."
self.finish_up
end
end
class SubClassC < SuperClass
def self.do_something
self.get_ready
puts "doing something crazy..."
self.finish_up
end
end
Run Code Online (Sandbox Code Playgroud)
如果您真的不愿意使用super,这几乎是不可能的。
使用super,这很简单:
class SuperClass
def do_something
puts "getting ready..."
yield
puts "done."
end
end
class SubClass < SuperClass
def do_something
super.do_something do
puts "doing something..."
end
end
end
Run Code Online (Sandbox Code Playgroud)
另一方面,super如果您对多种方法持开放态度,那么如果不使用,这会变得更简单:
class SuperClass
def do_something
puts "getting ready..."
self.actually_do_the_thing
puts "done."
end
def actually_do_the_thing
raise NotImplementedError
end
end
class SubClass < SuperClass
def actually_do_the_thing
puts "doing something..."
end
end
Run Code Online (Sandbox Code Playgroud)
在Ruby中的实用面向对象设计中,Sandi Metz建议您克服超级调用的方法是在超类中定义“钩子”方法,唯一的工作就是被子方法覆盖。在您的情况下,您可以执行以下操作:
class SuperClass
def self.do_something
puts "getting ready..."
do_something_child
puts "done."
end
def self.do_something_child; end
end
class SubClass < SuperClass
def self.do_something_child
puts "doing something ..."
end
end
SubClass.do_something
Run Code Online (Sandbox Code Playgroud)