網(wǎng)站首頁(yè) 編程語(yǔ)言 正文
Swift 的類(lèi)型推斷能力從一開(kāi)始就是語(yǔ)言的核心部分,它極大地減少了我們?cè)诼暶饔心J(rèn)值的變量和屬性時(shí)手動(dòng)指定類(lèi)型的工作。例如,表達(dá)式var number = 7
不需要包含任何類(lèi)型注釋?zhuān)驗(yàn)榫幾g器能夠推斷出值7
是一個(gè)Int
,我們的number
變量應(yīng)該被相應(yīng)的類(lèi)型化。
作為 Xcode 13.3 的一部分而一起發(fā)布的 Swift 5.6,通過(guò)引入 "類(lèi)型占位符(type placeholders) "的概念,繼續(xù)擴(kuò)展這些類(lèi)型推理能力,這在處理集合和其他通用類(lèi)型時(shí)非常有用。
例如,假設(shè)我們想創(chuàng)建一個(gè)Combine
里面具有默認(rèn)整數(shù)值的 CurrentValueSubject
的實(shí)例。關(guān)于如何做到這一點(diǎn)的初步想法可能是簡(jiǎn)單地將我們的默認(rèn)值傳遞給該主體的初始化器,然后將結(jié)果存儲(chǔ)在本地的一個(gè)let
聲明的屬性中(就像創(chuàng)建一個(gè)普通的Int
值時(shí)一樣)。然而,這樣做會(huì)給我們帶來(lái)以下編譯器錯(cuò)誤:
// Error: "Generic parameter 'Failure' could not be inferred" // Error: “無(wú)法被推斷出泛型的`Failure`參數(shù) ” let counterSubject = CurrentValueSubject(0)
這是因?yàn)?code>CurrentValueSubject是一個(gè)泛型類(lèi)型,實(shí)例化時(shí)不僅需要Output
類(lèi)型,還需要Failure
類(lèi)型——這是該主體能夠拋出的錯(cuò)誤類(lèi)型。
因?yàn)槲覀儾幌M覀兊闹黧w在這種情況下拋出任何錯(cuò)誤,所以我們會(huì)給它一個(gè)Failure
類(lèi)型的值Never
(這是在 Swift 中使用 Combine
的一個(gè)常見(jiàn)慣例)。但為了做到這一點(diǎn),在 Swift 5.6 之前,我們需要明確地指定我們的Int
輸出類(lèi)型——像這樣:
let counterSubject = CurrentValueSubject<Int, Never>(0)
不過(guò)從 Swift 5.6 開(kāi)始,這種情況就不存在了——因?yàn)槲覀儸F(xiàn)在可以使用一個(gè)類(lèi)型占位符來(lái)表示我們主體的Output
類(lèi)型,這讓我們?cè)俅卫镁幾g器為我們自動(dòng)推斷出該類(lèi)型,就像在聲明一個(gè)普通的Int
值一樣:
let counterSubject = CurrentValueSubject<_, Never>(0)
這很好,但可以說(shuō)這并不是 swift 里面很大的改進(jìn)。畢竟,我們用_
代替Int
只是節(jié)省了兩個(gè)字符,而且手動(dòng)指定像Int
這樣的簡(jiǎn)單類(lèi)型也不是一開(kāi)始就有問(wèn)題的。
**但現(xiàn)在讓我們看看這個(gè)功能如何擴(kuò)展到更復(fù)雜的類(lèi)型,這是它真正開(kāi)始發(fā)光的地方。**例如,假設(shè)我們的項(xiàng)目包含以下函數(shù),讓我們加載一個(gè)用戶注解的PDF文件:
func loadAnnotatedPDF(named: String) -> Resource<PDF<UserAnnotations>> { ... }
上面的函數(shù)使用了一個(gè)相當(dāng)復(fù)雜的泛型作為它的返回類(lèi)型,這可能是因?yàn)槲覀冃枰诙鄠€(gè)地方中重復(fù)使用我們的Resource
類(lèi)型,也因?yàn)槲覀冞x擇了使用*幻象類(lèi)型*來(lái)指定我們當(dāng)前處理的是哪種PDF。
現(xiàn)在讓我們看看,如果我們?cè)趧?chuàng)建主體時(shí)調(diào)用上述函數(shù),而不是僅僅使用一個(gè)簡(jiǎn)單的整數(shù),那么我們之前基于CurrentValueSubject
的代碼會(huì)是什么樣子:
// Before Swift 5.6: let pdfSubject = CurrentValueSubject<Resource<PDF<UserAnnotations>>, Never>( loadAnnotatedPDF(named: name) ) // Swift 5.6: let pdfSubject = CurrentValueSubject<_, Never>( loadAnnotatedPDF(named: name) )
這是一個(gè)相當(dāng)大的改進(jìn)啊 基于 Swift 5.6 的版本不僅為我們節(jié)省了一些輸入,而且由于 pdfSubject
的類(lèi)型現(xiàn)在完全來(lái)自 loadAnnotatedPDF
函數(shù),這可能會(huì)使該函數(shù)(及其相關(guān)代碼)的迭代更加容易——因?yàn)槿绻覀兏淖冊(cè)摵瘮?shù)的返回類(lèi)型,需要更新的手動(dòng)類(lèi)型注釋將減少。
不過(guò),值得指出的是,在上述情況下,還有另一種方法可以利用Swift的類(lèi)型推理能力——那就是使用類(lèi)型別名,而不是類(lèi)型占位符。例如,我們可以在這里定義一個(gè)UnfailingValueSubject
類(lèi)型別名,我們可以用它來(lái)輕松地創(chuàng)建不會(huì)產(chǎn)生任何錯(cuò)誤的主體:
typealias UnfailingValueSubject<T> = CurrentValueSubject<T, Never>
有了上述內(nèi)容,我們現(xiàn)在就可以在沒(méi)有任何泛型注解的情況下創(chuàng)建我們的pdfSubject
了——因?yàn)榫幾g器能夠推斷出T
指的是什么類(lèi)型,而且失敗類(lèi)型Never
已經(jīng)被硬編碼到我們的新類(lèi)型別名中:
let pdfSubject = UnfailingValueSubject(loadAnnotatedPDF(named: name))
但這并不意味著類(lèi)型別名在通常情況下都比類(lèi)型占位符好,因?yàn)槿绻覀円獮槊糠N特定情況定義新的類(lèi)型別名,那么這也會(huì)使我們的代碼庫(kù)變得更加復(fù)雜。有時(shí),在內(nèi)聯(lián)中指定所有的東西(比如使用類(lèi)型占位符時(shí))絕對(duì)是個(gè)好辦法,因?yàn)檫@可以讓我們定義完全獨(dú)立的表達(dá)式。
在我們總結(jié)之前,讓我們也來(lái)看看類(lèi)型占位符是如何與集合字面量(literals)一起使用的——例如在創(chuàng)建一個(gè)字典時(shí)。在這里,我們選擇手動(dòng)指定我們的字典的 Key
類(lèi)型(為了能夠使用點(diǎn)語(yǔ)法來(lái)指代枚舉的各種情況),同時(shí)為該字典的值使用一個(gè)類(lèi)型占位符:
enum UserRole { case local case remote } let latestMessages: [UserRole: _] = [ .local: "", .remote: "" ]
這就是類(lèi)型占位符——Swift 5.6 中引入的一個(gè)新功能,在處理稍微復(fù)雜的通用類(lèi)型時(shí),它可能真的很有用。但值得指出的是,這些占位符只能在調(diào)用站點(diǎn)使用,而不是在指定函數(shù)或計(jì)算屬性的返回類(lèi)型時(shí)使用。
總結(jié)
原文鏈接:https://juejin.cn/post/7108291937722957860
相關(guān)推薦
- 2022-08-07 Android?Gradle?插件自定義Plugin實(shí)現(xiàn)注意事項(xiàng)_Android
- 2022-10-23 C#泛型集合類(lèi)型實(shí)現(xiàn)添加和遍歷_C#教程
- 2022-07-30 基于docker安裝zabbix的詳細(xì)教程_zabbix
- 2022-08-17 yolov5中anchors設(shè)置實(shí)例詳解_python
- 2022-05-11 Python學(xué)習(xí)之私有函數(shù),私有變量及封裝詳解_python
- 2022-04-19 C語(yǔ)言雙指針?biāo)惴ㄅ笥堰^(guò)情人節(jié)我過(guò)算法_C 語(yǔ)言
- 2022-10-08 ASP.NET?MVC在基控制器中處理Session_實(shí)用技巧
- 2022-09-07 解析react?函數(shù)組件輸入卡頓問(wèn)題?usecallback?react.memo_React
- 最近更新
-
- window11 系統(tǒng)安裝 yarn
- 超詳細(xì)win安裝深度學(xué)習(xí)環(huán)境2025年最新版(
- Linux 中運(yùn)行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲(chǔ)小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎(chǔ)操作-- 運(yùn)算符,流程控制 Flo
- 1. Int 和Integer 的區(qū)別,Jav
- spring @retryable不生效的一種
- Spring Security之認(rèn)證信息的處理
- Spring Security之認(rèn)證過(guò)濾器
- Spring Security概述快速入門(mén)
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權(quán)
- redisson分布式鎖中waittime的設(shè)
- maven:解決release錯(cuò)誤:Artif
- restTemplate使用總結(jié)
- Spring Security之安全異常處理
- MybatisPlus優(yōu)雅實(shí)現(xiàn)加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務(wù)發(fā)現(xiàn)-Nac
- Spring Security之基于HttpR
- Redis 底層數(shù)據(jù)結(jié)構(gòu)-簡(jiǎn)單動(dòng)態(tài)字符串(SD
- arthas操作spring被代理目標(biāo)對(duì)象命令
- Spring中的單例模式應(yīng)用詳解
- 聊聊消息隊(duì)列,發(fā)送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠(yuǎn)程分支