Ruby中有什么方法可以基于继承的标准救援策略吗?
我想要这样的东西:
class Parent
def method
rescue StandardError => e
#handle error
end
end
class Child < Parent
def method
raise StandardError.new("ERROR") if error_present
#do some stuff
super
end
def error_present
#checks for errors
end
end
我期望的结果是,当StandardError
在孩子的方法中提出时,它将从父的方法定义中拯救出来。
如果这是不可能的,我还有其他方法可以实现这种行为吗?
恐怕这是不可能的——一种方法的rescue
只能挽救其体内产生的错误。
处理此问题的一种方法是提供另一种在子类中覆盖的方法:
class Parent
# This is the public interface of the class, it is not supposed to be overriden
def execute!
perform
rescue => e
# do_sth_with_error
end
private
# Private implementation detail, override at will
def perform
end
end
class Child < Parent
private
def perform
raise "Something" if something?
# do some more things
super
end
end
Child.new.execute!
话虽如此 - 请不要拯救StandardError
.这将使您未来的调试成为一场噩梦。请改为创建自己的错误子类。
你可以有这样的策略,但这取决于它应该如何工作以及你的代码是如何组织的。此模式可以扩展。对于您的特定情况,您可以按如下方式组织代码:
class Parent
def my_method(arg1, arg2)
yield if block_given?
# some code that should be run by Parent#my_method
rescue StandardError => e
# handle the error
end
end
class Child < Parent
def my_method(arg1, arg2)
super do
# code that should be run by Child#my_method
raise StandardError.new('error message') if error?
# maybe more code that should be run by Child#my_method
end
end
def error?
true
end
end
使用此策略,您必须将子方法中的所有代码作为块注入到父方法,通过唯一的语句super
调用传递给父方法(嗯,基本上它是继承链中传递的闭包)。当然,此策略假设您的方法不使用块来实现其正常逻辑,您可以专门将此功能用于此执行注入。
如果你想使用此策略进行两个以上的继承级别,则必须对每个下一个方法使用相同的技巧:
class C
def m1
yield if block_given?
# ...
rescue SomeError
# ...
end
end
class B < C
def m1
super do
yield if block_given?
# ...
end
end
end
class A < B
def m1
super do
raise SomeError if condition
# ...
end
end
end
如果应用此策略,您很可能可以删除if block_given?
部分。