<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
Swift 的型別推斷能力從一開始就是語言的核心部分,它極大地減少了我們在宣告有預設值的變數和屬性時手動指定型別的工作。例如,表示式var number = 7
不需要包含任何型別註釋,因為編譯器能夠推斷出值7
是一個Int
,我們的number
變數應該被相應的型別化。
作為 Xcode 13.3 的一部分而一起釋出的 Swift 5.6,通過引入 "型別預留位置(type placeholders) "的概念,繼續擴充套件這些型別推理能力,這在處理集合和其他通用型別時非常有用。
例如,假設我們想建立一個Combine
裡面具有預設整數值的 CurrentValueSubject
的範例。關於如何做到這一點的初步想法可能是簡單地將我們的預設值傳遞給該主體的初始化器,然後將結果儲存在原生的一個let
宣告的屬性中(就像建立一個普通的Int
值時一樣)。然而,這樣做會給我們帶來以下編譯器錯誤:
// Error: "Generic parameter 'Failure' could not be inferred" // Error: 「無法被推斷出泛型的`Failure`引數 」 let counterSubject = CurrentValueSubject(0)
這是因為CurrentValueSubject
是一個泛型型別,範例化時不僅需要Output
型別,還需要Failure
型別——這是該主體能夠丟擲的錯誤型別。
因為我們不希望我們的主體在這種情況下丟擲任何錯誤,所以我們會給它一個Failure
型別的值Never
(這是在 Swift 中使用 Combine
的一個常見慣例)。但為了做到這一點,在 Swift 5.6 之前,我們需要明確地指定我們的Int
輸出型別——像這樣:
let counterSubject = CurrentValueSubject<Int, Never>(0)
不過從 Swift 5.6 開始,這種情況就不存在了——因為我們現在可以使用一個型別預留位置來表示我們主體的Output
型別,這讓我們再次利用編譯器為我們自動推斷出該型別,就像在宣告一個普通的Int
值一樣:
let counterSubject = CurrentValueSubject<_, Never>(0)
這很好,但可以說這並不是 swift 裡面很大的改進。畢竟,我們用_
代替Int
只是節省了兩個字元,而且手動指定像Int
這樣的簡單型別也不是一開始就有問題的。
**但現在讓我們看看這個功能如何擴充套件到更復雜的型別,這是它真正開始發光的地方。**例如,假設我們的專案包含以下函數,讓我們載入一個使用者註解的PDF檔案:
func loadAnnotatedPDF(named: String) -> Resource<PDF<UserAnnotations>> { ... }
上面的函數使用了一個相當複雜的泛型作為它的返回型別,這可能是因為我們需要在多個地方中重複使用我們的Resource
型別,也因為我們選擇了使用*幻象型別*來指定我們當前處理的是哪種PDF。
現在讓我們看看,如果我們在建立主體時呼叫上述函數,而不是僅僅使用一個簡單的整數,那麼我們之前基於CurrentValueSubject
的程式碼會是什麼樣子:
// Before Swift 5.6: let pdfSubject = CurrentValueSubject<Resource<PDF<UserAnnotations>>, Never>( loadAnnotatedPDF(named: name) ) // Swift 5.6: let pdfSubject = CurrentValueSubject<_, Never>( loadAnnotatedPDF(named: name) )
這是一個相當大的改進啊 基於 Swift 5.6 的版本不僅為我們節省了一些輸入,而且由於 pdfSubject
的型別現在完全來自 loadAnnotatedPDF
函數,這可能會使該函數(及其相關程式碼)的迭代更加容易——因為如果我們改變該函數的返回型別,需要更新的手動型別註釋將減少。
不過,值得指出的是,在上述情況下,還有另一種方法可以利用Swift的型別推理能力——那就是使用型別別名,而不是型別預留位置。例如,我們可以在這裡定義一個UnfailingValueSubject
型別別名,我們可以用它來輕鬆地建立不會產生任何錯誤的主體:
typealias UnfailingValueSubject<T> = CurrentValueSubject<T, Never>
有了上述內容,我們現在就可以在沒有任何泛型註解的情況下建立我們的pdfSubject
了——因為編譯器能夠推斷出T
指的是什麼型別,而且失敗型別Never
已經被寫死到我們的新型別別名中:
let pdfSubject = UnfailingValueSubject(loadAnnotatedPDF(named: name))
但這並不意味著型別別名在通常情況下都比型別預留位置好,因為如果我們要為每種特定情況定義新的型別別名,那麼這也會使我們的程式碼庫變得更加複雜。有時,在內聯中指定所有的東西(比如使用型別預留位置時)絕對是個好辦法,因為這可以讓我們定義完全獨立的表示式。
在我們總結之前,讓我們也來看看型別預留位置是如何與集合字面量(literals)一起使用的——例如在建立一個字典時。在這裡,我們選擇手動指定我們的字典的 Key
型別(為了能夠使用點語法來指代列舉的各種情況),同時為該字典的值使用一個型別預留位置:
enum UserRole { case local case remote } let latestMessages: [UserRole: _] = [ .local: "", .remote: "" ]
這就是型別預留位置——Swift 5.6 中引入的一個新功能,在處理稍微複雜的通用型別時,它可能真的很有用。但值得指出的是,這些預留位置只能在呼叫站點使用,而不是在指定函數或計算屬性的返回型別時使用。
總結
到此這篇關於Swift型別預留位置的文章就介紹到這了,更多相關Swift型別預留位置內容請搜尋it145.com以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援it145.com!
相關文章
<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
综合看Anker超能充系列的性价比很高,并且与不仅和iPhone12/苹果<em>Mac</em>Book很配,而且适合多设备充电需求的日常使用或差旅场景,不管是安卓还是Switch同样也能用得上它,希望这次分享能给准备购入充电器的小伙伴们有所
2021-06-01 09:31:42
除了L4WUDU与吴亦凡已经多次共事,成为了明面上的厂牌成员,吴亦凡还曾带领20XXCLUB全队参加2020年的一场音乐节,这也是20XXCLUB首次全员合照,王嗣尧Turbo、陈彦希Regi、<em>Mac</em> Ova Seas、林渝植等人全部出场。然而让
2021-06-01 09:31:34
目前应用IPFS的机构:1 谷歌<em>浏览器</em>支持IPFS分布式协议 2 万维网 (历史档案博物馆)数据库 3 火狐<em>浏览器</em>支持 IPFS分布式协议 4 EOS 等数字货币数据存储 5 美国国会图书馆,历史资料永久保存在 IPFS 6 加
2021-06-01 09:31:24
开拓者的车机是兼容苹果和<em>安卓</em>,虽然我不怎么用,但确实兼顾了我家人的很多需求:副驾的门板还配有解锁开关,有的时候老婆开车,下车的时候偶尔会忘记解锁,我在副驾驶可以自己开门:第二排设计很好,不仅配置了一个很大的
2021-06-01 09:30:48
不仅是<em>安卓</em>手机,苹果手机的降价力度也是前所未有了,iPhone12也“跳水价”了,发布价是6799元,如今已经跌至5308元,降价幅度超过1400元,最新定价确认了。iPhone12是苹果首款5G手机,同时也是全球首款5nm芯片的智能机,它
2021-06-01 09:30:45