ruby是一门动态脚本语言,这个大家都知道。
我今天想讨论的问题是ruby中的异常处理机制,首先贴一段代码:
2 end
3
4 class Test
5 @host = " 192.168.0.1 "
6 @port = 8000
7 def opensocket
8 ret_str = " socket open Fail "
9 begin
10 socket = TCPSocket . open ( @host , @port )
11 ret_str = " socket open successed! "
12 rescue => e
13 puts " socket error "
14 raise SocketError
15 end
16 return ret_str
17 end
18 end
19
20 # ############################
21 t = Test . new
22 begin
23 str = t . opensocket()
24 puts str
25 rescue SocketError
26 puts " socket open fail in opensocket method "
27 end
28 # ############################
这段代码打印的结果大家都应该会知道:
socket error
socket open fail in opensocket method
在看下下面的这段代码
2 end
3
4 class Test
5 @host = " 192.168.0.1 "
6 @port = 8000
7 def opensocket
8 ret_str = " socket open Fail "
9 begin
10 socket = TCPSocket . open ( @host , @port )
11 ret_str = " socket open successed! "
12 rescue => e
13 puts " socket error "
14 raise SocketError
15 ensure
16 return ret_str
17 end
18 end
19 end
20
21 # ############################
22 t = Test . new
23 begin
24 str = t . opensocket()
25 puts str
26 rescue SocketError
27 puts " socket open fail in opensocket method "
28 end
29 # ############################
30
31
大家说这段代码返回的是什么?
还是和上面的代码返回的结果一致么?
结果是:
socket error
socket open Fail
大家可能想“为什么他能返回的结果是:socket open Fail ,在在外层的resure中为什么不能接收到异常呢?为什么不能打印 socket open fail in opensocket method“
今天要讨论的问题就是这个。
在第二段代码与第一段代码的不同就是:return 语句放置 的位置不同。在第二段代码中吧return 放在 ensure中 ,第一段代码则是放置在 begin ... end语言之后。
其实就是这点的原因导致了上面的结果。在代码段2中,我们只是在是希望在异常的善后处理中能把我们想要的值返回去。
这样做将导致一个结果就是,在之前的rescue中raise 的异常将因为这个return而被”吃“掉。 也就是说,这个时候的他就不把raise 这个异常往上抛了,自己处理了,
其实在强类型语言里是不允许在ensure中return的。
例如在C#语言中,在try...catch...finally 的 finally中是不允许有return的,这样就避免了这样的问题发生。