混合構(gòu)造器

作者:Russ Bishop脸狸,原文鏈接钳枕,原文日期:2016-11-09
譯者:Cyan缴渊;校對:小鐵匠Linus;定稿:CMB

今天的內(nèi)容非常簡單鱼炒,但是有些內(nèi)容會讓人產(chǎn)生困擾衔沼,通常出現(xiàn)在 extensions 的上下文或者和 RawRepresentable 的枚舉值打交道的時候。

無法委托給可失敗的構(gòu)造器

比如說你有個帶有可失敗構(gòu)造器的類型∥羟疲現(xiàn)在你想擴展這個類型讓他支持反序列化 JSON 數(shù)據(jù)指蚁。當 JSON 解析失敗的時候拋出一個友好且詳細的錯誤,并且你希望發(fā)生任何錯誤的時候都能夠拋出來自晰,不管是 JSON 解析還是可失敗初始化器中的錯誤欣舵,如果我們能拋出異常的話那是很好的。

struct FizzFail {
    init?(string: String) { /* magic */ }
    init(json: JsonValue) throws {
        // 解析 json
        guard let string = json.string else { throw JsonError.invalidJson }
        // 錯誤:不可失敗的構(gòu)造器無法委托給可失敗的構(gòu)造器
        if self.init(string: string) == nil {
            throw JsonError.missingValue
        }
    }
}

這里有兩個問題缀磕。首先是我們不能委托給可失敗構(gòu)造器缘圈。當有人嘗試傳遞一個不合法的 JSON 數(shù)據(jù)時(這是不常見的對吧?)袜蚕,編譯器會幫助我們將這個構(gòu)造器轉(zhuǎn)換到一個可失敗的構(gòu)造器糟把,或者是插入一個不安全的解包類型,然后會終止掉牲剃。

其次遣疯,即便我們可以檢查可失敗構(gòu)造器的結(jié)果,但沒有語法可以這樣做凿傅。self 在可失敗構(gòu)造器的上下文中只是一個可選值缠犀。

針對這個情況有三種解決方案:

1.如果擁有對應的類型,可以將實際初始化的代碼移到一個私有的可拋出異常的構(gòu)造器里面聪舒,然后公開的構(gòu)造器都委托它來進行初始化辨液。在可失敗構(gòu)造器里面使用 try? 來忽略錯誤。

struct Fizz {
    private init(value: String) throws { /* magic */ }
    init(json: JsonValue) throws {
        guard let string = json.string else {
            throw JsonError.invalidJson
        }
        try self.init(value: string)
    }
    init?(string: String) {
        try? self.init(value: string)
    }
}

2.如果不擁有類型并且它是一個值類型箱残,你可以對 self 重新賦值滔迈。這會導致額外的聲明和分配止吁,但是代碼看起來會更清晰。

extension FizzFail {
    init(json: JsonValue) throws {
        // 解析 json
        guard let string = json.string,
        let value = type(of: self).init(string: string) else {
            throw JsonError.invalidJson
        }
        self = value
    }
}

3.如果不擁有類型并且它是一個引用類型燎悍,那么你必須使用一個靜態(tài)方法來解決敬惦,因為你沒有更好的選擇了。

原始值

上面的技巧同樣適用于含有原始值(RawValue)的枚舉值谈山。即使你擁有類型俄删,你也不擁有自動生成的構(gòu)造器,所以只能對 self 重新賦值:

enum Buzz: String {
    case wat = "wat"
    case other = "other"

    private enum ConstructionError: Error {
        case invalidConstruction
    }

    init(string: String) {
        if let value = type(of: self).init(rawValue: string) {
            self = value
        } else {
            self = .other
        }
    }
}

結(jié)束語

我在 30 分鐘里寫完了這篇文章是為了讓你知道奏路,其實我的博客還在維護畴椰,最后謝謝你讀完。

Russ Bishop
這個博客僅代表我個人的觀點思劳,并沒有得到我的雇主的認可迅矛。

本文由 SwiftGG 翻譯組翻譯妨猩,已經(jīng)獲得作者翻譯授權(quán)潜叛,最新文章請訪問 http://swift.gg

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末壶硅,一起剝皮案震驚了整個濱河市威兜,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌庐椒,老刑警劉巖椒舵,帶你破解...
    沈念sama閱讀 211,948評論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異约谈,居然都是意外死亡笔宿,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,371評論 3 385
  • 文/潘曉璐 我一進店門棱诱,熙熙樓的掌柜王于貴愁眉苦臉地迎上來泼橘,“玉大人,你說我怎么就攤上這事迈勋【婷穑” “怎么了?”我有些...
    開封第一講書人閱讀 157,490評論 0 348
  • 文/不壞的土叔 我叫張陵靡菇,是天一觀的道長重归。 經(jīng)常有香客問我,道長厦凤,這世上最難降的妖魔是什么鼻吮? 我笑而不...
    開封第一講書人閱讀 56,521評論 1 284
  • 正文 為了忘掉前任,我火速辦了婚禮较鼓,結(jié)果婚禮上狈网,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好拓哺,可當我...
    茶點故事閱讀 65,627評論 6 386
  • 文/花漫 我一把揭開白布勇垛。 她就那樣靜靜地躺著,像睡著了一般士鸥。 火紅的嫁衣襯著肌膚如雪闲孤。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,842評論 1 290
  • 那天烤礁,我揣著相機與錄音讼积,去河邊找鬼。 笑死脚仔,一個胖子當著我的面吹牛勤众,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播鲤脏,決...
    沈念sama閱讀 38,997評論 3 408
  • 文/蒼蘭香墨 我猛地睜開眼们颜,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了猎醇?” 一聲冷哼從身側(cè)響起窥突,我...
    開封第一講書人閱讀 37,741評論 0 268
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎硫嘶,沒想到半個月后阻问,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,203評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡沦疾,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,534評論 2 327
  • 正文 我和宋清朗相戀三年称近,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片哮塞。...
    茶點故事閱讀 38,673評論 1 341
  • 序言:一個原本活蹦亂跳的男人離奇死亡刨秆,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出彻桃,到底是詐尸還是另有隱情坛善,我是刑警寧澤,帶...
    沈念sama閱讀 34,339評論 4 330
  • 正文 年R本政府宣布邻眷,位于F島的核電站眠屎,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏肆饶。R本人自食惡果不足惜改衩,卻給世界環(huán)境...
    茶點故事閱讀 39,955評論 3 313
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望驯镊。 院中可真熱鬧葫督,春花似錦竭鞍、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,770評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至洽胶,卻和暖如春晒夹,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背姊氓。 一陣腳步聲響...
    開封第一講書人閱讀 32,000評論 1 266
  • 我被黑心中介騙來泰國打工丐怯, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人翔横。 一個月前我還...
    沈念sama閱讀 46,394評論 2 360
  • 正文 我出身青樓读跷,卻偏偏與公主長得像,于是被迫代替她去往敵國和親禾唁。 傳聞我的和親對象是個殘疾皇子效览,可洞房花燭夜當晚...
    茶點故事閱讀 43,562評論 2 349

推薦閱讀更多精彩內(nèi)容

  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理,服務發(fā)現(xiàn)蟀俊,斷路器钦铺,智...
    卡卡羅2017閱讀 134,633評論 18 139
  • importUIKit classViewController:UITabBarController{ enumD...
    明哥_Young閱讀 3,783評論 1 10
  • // 這章比較重要 //構(gòu)造//“構(gòu)造過程是使用類订雾、結(jié)構(gòu)體或枚舉類型的實例之前的準備過程肢预。在新實例可用前必須執(zhí)行這...
    你weixiao的時候很美閱讀 394評論 0 0
  • 本章將會介紹 存儲屬性的初始賦值自定義構(gòu)造過程默認構(gòu)造器值類型的構(gòu)造器代理類的繼承和構(gòu)造過程可失敗構(gòu)造器必要構(gòu)造器...
    寒橋閱讀 769評論 0 0
  • 今天又沒有復習烫映,而且起得更晚了。但是這兩天看書很快噩峦,讀了《失樂園》和《愛你就像愛生命》锭沟。 看王小波給李銀河的書信,...
    ZhenMIng閱讀 223評論 0 0