自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

Swift擴(kuò)展的三個(gè)微妙細(xì)節(jié)

移動(dòng)開發(fā) iOS 開發(fā)
每當(dāng)我初次翻看某文檔時(shí),我都走馬觀花似的快速閱過,還一邊點(diǎn)著頭一邊喃喃自語說:“好!懂了,就這么回事!”,可是過后當(dāng)我真正要運(yùn)用到這些我以為已經(jīng)理解了的知識(shí)點(diǎn)時(shí),卻發(fā)現(xiàn)實(shí)際情況和我想的往往不一樣,每當(dāng)這時(shí)我就懵了,心想:“哇哦…怎么回事?這和我想的完全不一樣??!文檔里有說這事嗎?”。

每當(dāng)我初次翻看某文檔時(shí),我都走馬觀花似的快速閱過,還一邊點(diǎn)著頭一邊喃喃自語說:“好!懂了,就這么回事!”,可是過后當(dāng)我真正要運(yùn)用到這些我以為已經(jīng)理解了的知識(shí)點(diǎn)時(shí),卻發(fā)現(xiàn)實(shí)際情況和我想的往往不一樣,每當(dāng)這時(shí)我就懵了,心想:“哇哦…怎么回事?這和我想的完全不一樣?。∥臋n里有說這事嗎?”。

最近的幾次討論促使我捫心自問是否真正的理解了Swift中的擴(kuò)展。我閱讀過關(guān)于擴(kuò)展的文檔,并且我“認(rèn)為”我自己對這塊內(nèi)容已經(jīng)是理解的相當(dāng)透徹了??墒沁@幾次討論,加上自己私下通過敲代碼的驗(yàn)證,讓我發(fā)現(xiàn)了我原先不曾注意到幾個(gè)微妙的細(xì)節(jié)。

更新:這篇文章剛一發(fā)表,Swift社區(qū)就出手襄助并幫助我弄明白了我最根本的糾結(jié)點(diǎn)在哪。為此,我寫了另一篇文章“闡明Swift訪問控制”進(jìn)一步說明我之前的誤解。為了避免犯我曾今犯過的錯(cuò)誤,我建議大家去讀一讀。

三個(gè)關(guān)于擴(kuò)展的微妙細(xì)節(jié)

對下面列出的三個(gè)細(xì)節(jié)的思考嚴(yán)重挑戰(zhàn)了我之前對Swift擴(kuò)展的理解:

Swift擴(kuò)展對它所擴(kuò)展類型的visibility。比如,擴(kuò)展能訪問被private所修飾的內(nèi)容嗎?

定義擴(kuò)展的位置是否對擴(kuò)展的visibility有影響。比如我這有一個(gè)類型我想寫個(gè)擴(kuò)展,把擴(kuò)展寫在同一個(gè)源文件里和把擴(kuò)展寫在另一個(gè)文件里有什么區(qū)別嗎?

擴(kuò)展里“成員”的默認(rèn)訪問修飾符以及是否給他們添加修飾對這個(gè)擴(kuò)展作為一個(gè)類型的公共接口的影響。

在我開始之前,假設(shè)我有一個(gè)公共結(jié)構(gòu)體Person。這個(gè)結(jié)構(gòu)體有一些私有屬性,name,gender,和age。用一個(gè)枚舉把Gender封裝了一下。這個(gè)結(jié)構(gòu)體看起來如下:

  1. public struct Person { 
  2.     private var name: String 
  3.     private var gender: Gender 
  4.     private var age: Int 
  5.    
  6.     public init(name: String, gender: Gender, age: Int) { 
  7.         self.name = name 
  8.         self.gender = gender 
  9.         self.age = age 
  10.     } 
  11.    
  12.     public func howOldArdYou() -> String { 
  13.         return formattedAge() 
  14.     } 
  15.    
  16.     // 私有方法,用于下面分析擴(kuò)展的`visibility`... 
  17.     private func formattedAge() -> String { 
  18.         switch self.gender { 
  19.         case .Male: 
  20.             return "I'm \(self.age)." 
  21.         case .Female: 
  22.             return "Not telling." 
  23.         } 
  24.     } 
  25.    
  26.     public enum Gender { 
  27.         case Male 
  28.         case Female 
  29.     } 

現(xiàn)在,就讓我們給Person寫個(gè)擴(kuò)展,通過實(shí)踐來弄清楚剛剛提到的三個(gè)小細(xì)節(jié)…

擴(kuò)展對類型的訪問能力

當(dāng)我提出***個(gè)細(xì)節(jié)時(shí),關(guān)于擴(kuò)展對被擴(kuò)展類型的訪問能力時(shí),我問了一個(gè)問題:“擴(kuò)展能訪問到被private修飾的內(nèi)容嗎?”。答案一開始出乎我的預(yù)料:能…擴(kuò)展能訪問到。

然而,這里就要考慮到第二個(gè)細(xì)節(jié)所涉及的問題,那就是:在哪里定義這個(gè)擴(kuò)展是絕對有影響的。

定義在同一個(gè)文件里

如果擴(kuò)展和類型是在寫同一個(gè)源文件里,則擴(kuò)展能訪問到在類型中被priavte所修飾的內(nèi)容。

舉個(gè)栗子,在Person.swift里定義一個(gè)Person的擴(kuò)展就會(huì)允許這個(gè)擴(kuò)展訪問被private修飾的變量和方法

  1. extension Person { 
  2.     func getAge() -> Int { 
  3.         return age // 盡管age是 --private--, 但編譯成功 
  4.     } 
  5.    
  6.     func getFormattedAge() -> String { 
  7.         return formattedAge() // 盡管 formattedAge是 --private--,但編譯成功 
  8.     } 

至于為什么把擴(kuò)展寫在同一個(gè)源文件里頭會(huì)這樣,我自己的推理是其實(shí)可以在寫類型的時(shí)候,就把擴(kuò)展的implementation當(dāng)作類型的一部分給寫了,這樣的最終效果是一樣的。“這誰知道?!什么??為啥?”,我當(dāng)時(shí)就沒想明白…

我在我要“擴(kuò)展”的類型的源文件里,所以無論是我把要新添加的功能當(dāng)作這個(gè)類型的擴(kuò)展寫下來,或是就在這個(gè)類型里面定義我原本打算寫在擴(kuò)展里的功能是沒有區(qū)別的,都是一樣的效果。

所以,站在編譯器的角度來看,編譯器可能會(huì)說:“好吧,我看到這里寫了一個(gè)擴(kuò)展,但是真沒這個(gè)必要,因?yàn)閿U(kuò)展和類型都在同一個(gè)源文件里…,所以開發(fā)者完全可以把擴(kuò)展里的這些代碼直接寫在類型里面…,所以他/她能夠訪問到被private修飾的代碼段。”

更新:我上面的寫的推理恰恰說明了我壓根就沒搞明白Swift訪問控制機(jī)制。所以我建議大家讀一讀我后來寫的“闡明Swfit控制機(jī)制”這篇文章,里面有更多的細(xì)節(jié)。

定義在不同文件里

把擴(kuò)展寫在另一個(gè)文件里,則擴(kuò)展無法訪問類型中那些被private修飾的內(nèi)容了。

按照上文我自己推理的邏輯來反過來想,定義在不同文件中就訪問不了私有屬性對我來說也是說的通的。

大多數(shù)情況下,你都會(huì)給那些你沒有源代碼的類型擴(kuò)展,在這種情況下,擴(kuò)展就只能訪問那些被public修飾的內(nèi)容了。

默認(rèn)情況下的擴(kuò)展訪問控制

對***一個(gè)細(xì)節(jié)的驗(yàn)證也讓我更深的體會(huì)。蘋果官方文檔說了,但是直到我動(dòng)手驗(yàn)證了一番,我才算領(lǐng)會(huì)到了默認(rèn)訪問控制修飾符給擴(kuò)展所造成的微妙的影響。

沒有明確聲明訪問修飾賦時(shí)的默認(rèn)訪問

簡單的說,當(dāng)你聲明一個(gè)擴(kuò)展但沒有特別明確指明訪問修飾符時(shí)(默認(rèn)情況下),這個(gè)擴(kuò)展的默認(rèn)訪問等級取決于被擴(kuò)展的那個(gè)類型的訪問等級。
* 如果類型是public或者是internal,那么擴(kuò)展的implementation的“成員”就默認(rèn)為internal。這里讓我沒想到是,除非你特別聲明,那么給public類型的擴(kuò)展的成員變量在默認(rèn)情況下也是internal。
* 如果類型是private,那么默認(rèn)情況下擴(kuò)展的implementation中的“成員”也是private

下面就是在我們不明確的聲明添加什么訪問修飾的前提下,來看擴(kuò)展會(huì)是一個(gè)什么反應(yīng)(為了能訪問私有屬性變量和方法,我在Person.swift里定義了這個(gè)擴(kuò)展):

  1. public struct Person { 
  2.     // ... 
  3.    
  4.     // ... 
  5.    
  6. extension Person { 
  7.     func getAge() -> Int { 
  8.         return age 
  9.     } 
  10.    
  11.     func getFormattedAge() -> String { 
  12.         return formattedAge() 
  13.     } 

同一模塊像上面這段代碼用默認(rèn)的訪問修飾符時(shí)就會(huì)允許在同一個(gè)模塊中的實(shí)例訪問擴(kuò)展里的API。但是,如果被擴(kuò)展的類型的實(shí)例是在另一個(gè)模塊(比如在測試模塊),則無法訪問擴(kuò)展中任何新增的公共API。
同一模塊

不同模塊(測試)

因?yàn)槟承┰?,我一直都以為如果給一個(gè)是public的類型添加擴(kuò)展,那么擴(kuò)展里的成員也理應(yīng)是public。我不知道為什么我會(huì)這么想,但是幸好我的驗(yàn)證把這點(diǎn)捋清楚了。

#p#

正常聲明擴(kuò)展,但給擴(kuò)展的implementation添加public修飾

給擴(kuò)展的implementation的成員添加了public訪問控制修飾,那么不管是在同一模塊還是不同模塊(test target)都能訪問這些成員。

只要成員被public修飾,那么在同一個(gè)源文件里聲明擴(kuò)展還是在另一個(gè)文件里聲明擴(kuò)展已經(jīng)無所謂了…但是,正如前文所講,只有在同一個(gè)源文件中聲明的擴(kuò)展才能夠訪問那些被private修飾的類型成員變量。

在不同(左)和同一個(gè)(右)源文件中聲明的擴(kuò)展

在不同模塊中也能訪問公共的擴(kuò)展成員變量

這里請注意,在我寫extension Person {...}時(shí),我沒有給這個(gè)擴(kuò)展添加任何的修飾,我只是給這個(gè)擴(kuò)展的成員添加了public。即便如此,新添加的方法仍然可以在不同的模塊中被訪問到。

也就是說,沒有必要寫public extension Person {...}。因?yàn)镻erson已經(jīng)是public了,所以基于Person的擴(kuò)展也就很自然的延用了類型本身的訪問等級。

總結(jié)

對我來說,這篇文章所提到的三個(gè)關(guān)于Swift擴(kuò)展的細(xì)節(jié)已足以讓我敲敲代碼去驗(yàn)證一番了。我希望這里所作的分析能夠?yàn)槟切﹪L試?yán)斫釹wfit擴(kuò)展的朋友掃清一些障礙。

責(zé)任編輯:chenqingxiang 來源: 開發(fā)技術(shù)前線
相關(guān)推薦

2011-01-19 13:11:25

Zimbra白名單證書

2011-05-10 16:27:55

網(wǎng)站優(yōu)化SEO

2009-01-10 19:38:00

服務(wù)器ServerCPU

2022-02-26 16:10:51

Figma設(shè)計(jì)工具

2022-02-14 10:42:41

移動(dòng)端標(biāo)簽設(shè)計(jì)用戶

2020-07-13 10:20:01

人工智能技術(shù)IT

2015-07-08 14:18:44

可擴(kuò)展架構(gòu)設(shè)計(jì)云計(jì)算

2016-04-29 15:19:01

企業(yè)軟件插件定制開源

2023-04-26 11:14:11

IT領(lǐng)導(dǎo)者遠(yuǎn)程工作

2012-03-14 13:27:18

筆記本常見問題

2019-01-16 08:05:56

2019-07-31 08:56:07

故障JavaBlockingQue

2020-06-11 09:00:27

SDN網(wǎng)絡(luò)架構(gòu)網(wǎng)絡(luò)

2017-06-05 13:53:10

2009-04-10 01:22:59

2021-09-01 13:37:16

物聯(lián)網(wǎng)可擴(kuò)展性IoT

2024-10-17 08:58:31

2023-03-07 17:56:09

Docker容器開源

2018-05-15 16:12:59

Kotlin擴(kuò)展XxxUtils

2022-02-21 14:14:03

SSH加密密鑰
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號