[2014年學習計劃之RoR系列] 第二步 – 熟悉Ruby語言 (3/n)

來源:互聯網
上載者:User

Ruby中的異常處理

Ruby預定義了常見的異常類型,如所示:


所有的異常類都從基類Exception派生出來,這一點跟Java, C#, Python都是類似的。

Ruby特別點的地方 - 當有異常發生時,ruby會將與這個異常相關聯的的異常對象放到全域變數$!中去。(這段有點不那麼清晰,理解中。。。附上原文吧)

When an exception is raised, and independent of any subsequent exception handling, Ruby places a reference to the associated Exception object into the global variable $!(The exclamation point presumably mirroring our surprise that any of our code could cause errors).

異常處理的例子:

begin
    eval string
rescue SyntaxError, NameError => boom
    print "String doesn't compile: " + boom
rescue StandardError => bang
    print "Error running script: " + bang
end

Ruby使用的是rescue關鍵字過濾異常,不同於其他語言中常見的catch。在begin塊中可以有多個rescue,而且每個rescue可以有多個異常類型。

如果rescue後邊沒有型別參數,那麼Ruby使用StandardError作為預設值。

系統錯誤

在POSIX系統上,errno是一個事實上的標準。系統或應用程式都使用errno來報告錯誤。Ruby將這些錯誤封裝成異常,這些異常類都是派生自SystemCallError。我們可以從類名上看出它們,例如Errno::EIO, Errno::EGAAIN等等。

這些類的Errno欄位可以一一對應系統的errno值。

Errno::EAGAIN::Errno 35
Errno::EPERM::Errno 1
Errno::EIO::Errno 5
Errno::EWOULDBLOCK::Errno 35
   

 

有了try/catch,那麼有沒有finally?

這個可以有。ensure就是我們要的東西。很直白,就不說了吧。

f = File.open("testfile")
begin
    # .. process
rescue
    # .. handle error
ensure
    f.close unless f.nil?
end

再來看點特別的東西 – else

f = File.open("testfile")
begin
    # .. process
rescue
    # .. handle error
else
    puts "Congratulations no  errors!"
ensure
    f.close unless f.nil?
end

rescue後面的else子句會在沒有異常拋出的時候被執行到。- 好像這個真沒什麼用啊。

下面上點有用的耍耍。

@esmtp = true
begin
    # First try an extended login. If it fails because the
    # server doesn't support it, fall back to a normal login
    if @esmtp then
        @command.ehlo(helodom)
    else
        @command.helo(helodom)
    end
rescue ProtocolError
    if @esmtp then
        @esmtp = false
        retry
    else
        raise
    end
end

有意思的地方就是那個紅色加粗的retry。上面這段代碼先將esmtp設定為true試著登陸,如果不成功就置為false重試。嗯,我覺得還是挺有用的。

說完了怎麼捕獲異常,下面該輪到拋出異常

raise
raise "bad mp3 encoding"
raise InterfaceException, "Keyboard failure", caller

這裡的raise實際上是Kernel.raise方法。

第一個raise沒有帶任何參數,它用來將當前的異常再向外層拋出。如果當前沒有異常,那麼將會拋出一個RuntimeError。

第二個raise帶有一個字串參數,這個參數被用來構造一個RuntimeError的異常,然後被拋出。

第三個raise帶有3個參數,第一個是異常類型,第二個是異常的訊息,第三個是call stack。Kernel.caller用來產生呼叫堆疊。

Ruby中真真兒的catch/throw是這樣用滴

當有錯誤發生的時候,如何從層層負責邏輯中跳出來?C-style longjump? No, Ruby提供了catch/throw的方便用法。

catch (:done) do
    while line = gets
        throw :done unless fields = line.split(/\t/)
        songlist.add(Song.new(*fields))
    end
    songlist.play
end

catch在這裡定義了一個名字為done的代碼塊,這個代碼塊正常執行直到遇到異常或正常結束。

又一個例子:

def prompt_and_get(prompt)
    print prompt
    res = readline.chomp
    throw :quit_requested if res == "!"
    res
end

catch :quit_requested do
    name = prompt_and_get("Name: ")
    age = prompt_and_get("Age: ")
    sex = prompt_and_get("Sex: ")
    # ..
    # process information
end

春節前的ruby筆記就到這裡了。祝大家馬上有錢,馬上有房,馬上有對象。




相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.