基本上,这是正常的代码:
class Foo
def hi
# your code here....
rescue => e
# Raise error here
end
def hello
# your code here...
rescue => e
# Raise error here
end
end
但在PHP中,我可以使用__call
魔术方法来创建抽象类,如下所示:
class FooAbstract {
public function __call($name, $args) {
# Try catch in here...
}
}
class Foo extends FooAbstract {
public function hi() {
# Code with try catch...
}
}
如何在Ruby类中使用__call方法???
答案 0 :(得分:1)
我不确定你想在这里实现什么,但PHP的__call()
的Ruby等价物是method_missing
。
默认情况下,当您尝试调用不存在的方法时,您将收到异常。但是如果你想实现一个"抽象类"。您也可以尝试此解决方案:https://stackoverflow.com/a/512505/185870
答案 1 :(得分:1)
你可以定义一个模块,当包含它时定义一个method_added
钩子,它将所有新方法包装在begin..rescue
块中:
require 'set'
module ExceptionHandler
def self.included(klass)
super
klass.send(:extend, ClassMethods)
end
module ClassMethods
def exception_handler(&block)
@__exception_handler = block.to_proc
end
def handle_exception(exception)
defined?(@__exception_handler) ? @__exception_handler.call(exception) : super
end
def handle_method_exceptions(method_name)
old_method = instance_method(method_name)
return if (@__hooked_methods ||= Set.new).include?(method_name)
@__ignoring_added_methods = true # avoid infinite define_method/method_added loop
define_method method_name do |*args, &block|
begin
old_method.bind(self).(*args, &block)
rescue => ex
self.class.handle_exception(ex)
end
end
@__ignoring_added_methods = false
@__hooked_methods << method_name
end
def method_added(method_name)
super
unless @__ignoring_added_methods
handle_method_exceptions(method_name)
end
end
end
end
这将用作:
class Foo
include ExceptionHandler
exception_handler do |exception|
puts "Catched an exception:"
puts "---------------------"
puts "Exception class: #{exception.class}"
puts "Message: #{exception.message}"
puts "Backtrace:"
puts exception.backtrace.join("\n ")
puts
puts "reraising.."
puts
raise exception
end
def this_raises
raise "somebody set up us the bomb"
end
end
Foo.new.this_raises
这将输出:
Catched an exception:
---------------------
Exception class: RuntimeError
Message: somebody set up us the bomb
Backtrace:
errorhandler.rb:62:in `this_raises'
errorhandler.rb:26:in `call'
errorhandler.rb:26:in `block in handle_exceptions'
errorhandler.rb:67:in `<main>'
reraising..
我不确定这是不是一个好主意。
您可以取出method_added
部分,它看起来像:
class Foo
with_rescue def foofoo(arg)
puts arg.inspect
end
end
(您可以将handle_method_exceptions
重命名为with_rescue
并删除所有@__ignoring_added_methods
欺骗和method_added
方法,它应按照描述运行。