2015-11-18 57 views
3

處理可能在Swift中失敗的init的最佳方法是什麼?例如,您可以創建一個依賴於可能不可用的特定資源的類實例。Swift初始者的錯誤

顯然,我們有兩個選擇:

  • 一個保釋的init返回零(可可方式)
  • 拋出一個錯誤的初始化

見下

enum ThingError: ErrorType{ 
    case crap 
} 
class Thing { 
    init(c: Int) throws{ 
     if c < 0 { 
      throw ThingError.crap 
     } 
    } 
} 



var c = try Thing(c: 3) 

do{ 
    var d = try Thing(c: -4) 
}catch{ 
    print("oh vey!") 
} 

有沒有推薦的方法呢?第二種選擇似乎更「Swifty」...

回答

6

既不是天生更好或Swiftier。

我個人覺得throws初始化者有巨大的痛苦。我寧願有一個失敗的初始化程序返回nil,因爲然後我可以使用guard let進行初始化,而不必將其包裝在do/catch中,並處理由此產生的範圍問題。你的代碼說明了這個問題。您的var d在「do」範圍內「卡住」。我寧願這樣說:

guard let d = Thing(c:-4) else {return} 
// now d is unwrapped and in scope! 

...比這個(你有什麼說的):

do { 
    var d = try Thing(c: -4) 
} catch { 
    print("oh vey!") 
} 
// and here there is no `d`, so _now_ what? 

在另一方面,拋出一個錯誤提供了一個機會來發送消息,即關於到底發生了什麼錯誤,是溝通。你不能僅僅通過init?初始化器來完成;它工作或失敗,這就是所有來電者都知道的。

+0

「有多少次遇到可能以多種方式失敗的init」所有時間@Grimxn。我立即想到了'initWithContentsOfURL:encoding:error:',並且有很多很多其他的東西。正因如此,在Objective-C中,這樣的方法有一個'error:'指針參數。該參數告訴你我們失敗了。 – matt

+0

「最常見的是零或一種方式失敗,單一失敗應該使用failable ......」而且,@Grimxn,我相信,這就是我的答案,不是嗎? – matt

+0

你是對的 - 除了記錄我自己的慢速理解之外,我在這裏什麼也沒有添加。將您的評論示例添加到答案中,我將刪除我的評論。 – Grimxn