答“卓同學(xué)的 Swift 面試題”--上篇

這是卓同學(xué)的 Swift 面試題 強(qiáng)行來答一波叨叙,如有歧義、錯(cuò)誤堪澎、不全擂错,歡迎指(來)正(噴)。
面試題基礎(chǔ)篇有36題樱蛤,高級篇8題钮呀,哲學(xué)篇2題。先就基礎(chǔ)篇前11題進(jìn)行回答昨凡。也為接下來的面試做些準(zhǔn)備 ??

1. class 和 struct 的區(qū)別
2. 不通過繼承爽醋,代碼復(fù)用(共享)的方式有哪些
3. Set 獨(dú)有的方法有哪些?
4. 實(shí)現(xiàn)一個(gè) min 函數(shù)便脊,返回兩個(gè)元素較小的元素
5. map子房、filter、reduce 的作用
6. map 與 flatmap 的區(qū)別
7. 什么是 copy on write
8. 如何獲取當(dāng)前代碼的函數(shù)名和行號
9. 如何聲明一個(gè)只能被類 conform 的 protocol
10. guard 使用場景
11. defer 使用場景
1. class 和 struct 的區(qū)別

此題可參見 The Swift Programming Language就轧,有專門的一節(jié)是用來介紹class 和 struct 的证杭。我也是從中總(搬)結(jié)(運(yùn))來的。
在 Swift 中妒御,class 和 struct 的關(guān)系可以說是非常之親密解愤。
相同點(diǎn): 我們可以使用完全使用相同的語法規(guī)則來為 class 和 struct 定義屬性、方法乎莉、下標(biāo)操作送讲、構(gòu)造器,也可以通過extension 和 protocol 來提供某種功能惋啃。
不同點(diǎn):
1)與 struct 相比哼鬓,class 還有如下功能:

  • 繼承允許一個(gè)類繼承另一個(gè)類的特性
  • 類型轉(zhuǎn)換允許在運(yùn)行時(shí)檢查和解釋一個(gè)類實(shí)例的類型
  • 析構(gòu)器允許一個(gè)類實(shí)例釋放任何其所被分配的資源
  • 引用計(jì)數(shù)允許對一個(gè)類的多次引用

2) Value Types & Reference Types:

  • struct 是值類型 (Value Types) 即:通過被復(fù)制的方式在代碼中傳遞,不使用引用計(jì)數(shù)
  • class 是引用類型(Reference Types) 即:引用類型在被賦予到一個(gè)變量边灭、常量或者被傳遞到一個(gè)函數(shù)時(shí)异希,其值不會(huì)被拷貝。因此绒瘦,引用的是已存在的實(shí)例本身而不是其拷貝

3) 分配方式

4) 方法派發(fā)

更多關(guān)于值類型和引用類型的知識称簿,請參見Value Types & Reference Types

2. 不通過繼承,代碼復(fù)用(共享)的方式有哪些

我們都知道代碼復(fù)用的好處:可以降低開發(fā)成本、增加代碼的可靠性并提高它們的一致性。
在Swift中螟深,除了通過繼承猪贪,還可以通過** * 擴(kuò)展、協(xié)議* ** 來實(shí)現(xiàn)代碼復(fù)用。

擴(kuò)展 --- Extensions

擴(kuò)展 就是為一個(gè)已有的類米奸、結(jié)構(gòu)體师倔、枚舉類型或者協(xié)議類型添加新功能悔叽。這包括在沒有權(quán)限獲取原始源代碼的情況下擴(kuò)展類型的能力(即 逆向建模 )航邢。擴(kuò)展和 Objective-C 中的分類類似。

Swift 中的擴(kuò)展可以:

  • 添加計(jì)算型屬性和計(jì)算型類型屬性
  • 定義實(shí)例方法和類型方法
  • 提供新的構(gòu)造器
  • 定義下標(biāo)
  • 定義和使用新的嵌套類型
  • 使一個(gè)已有類型符合某個(gè)協(xié)議

更多擴(kuò)展知識骄蝇,請移步:Extensions

協(xié)議 --- Protocols

協(xié)議 規(guī)定了用來實(shí)現(xiàn)某一特定任務(wù)或者功能的方法膳殷、屬性,以及其他需要的東西九火。類赚窃、結(jié)構(gòu)體或枚舉都可以遵循協(xié)議,并為協(xié)議定義的這些要求提供具體實(shí)現(xiàn)
另外岔激,規(guī)定了用來實(shí)現(xiàn)某一特定任務(wù)或者功能的方法勒极、屬性,以及其他需要的東西虑鼎。類辱匿、結(jié)構(gòu)體或枚舉都可以遵循協(xié)議,并為協(xié)議定義的這些要求提供具體實(shí)現(xiàn)

這里只是簡單敘述下炫彩,更多協(xié)議知識匾七,請移步:Protocols

3. Set 獨(dú)有的方法有哪些
intersect(_:)// 根據(jù)兩個(gè)集合中都包含的值創(chuàng)建的一個(gè)新的集合
exclusiveOr(_:) // 根據(jù)只在一個(gè)集合中但不在兩個(gè)集合中的值創(chuàng)建一個(gè)新的集合
union(_:) // 根據(jù)兩個(gè)集合的值創(chuàng)建一個(gè)新的集合
subtract(_:) //根據(jù)不在該集合中的值創(chuàng)建一個(gè)新的集合
isSubsetOf(_:) //判斷一個(gè)集合中的值是否也被包含在另外一個(gè)集合中
isSupersetOf(_:) //判斷一個(gè)集合中包含的值是否含有另一個(gè)集合中所有的值
isStrictSubsetOf(:) isStrictSupersetOf(:) //判斷一個(gè)集合是否是另外一個(gè)集合的子集合或者父集合并且和特定集合不相等
isDisjointWith(_:) //判斷兩個(gè)集合是否不含有相同的值

let houseAnimals : Set = ["?","?"]
let farmAnimals: Set = ["?","?","?","?","?"]
let cityAnimals: Set = ["?","?"]
houseAnimals. isSubsetOf(farmAnimals)
//true
farmAnimals. isSupersetOf(houseAnimals)
//true
farmAnimals. isDisjointWith(cityAnimals)
//true
集合的基本操作
4.實(shí)現(xiàn)一個(gè) min 函數(shù),返回兩個(gè)元素較小的元素
func min<T: Comparable>(_ a: T, _ b: T) -> T {
    return a < b ? a: b
}
//這里一定要遵守 Comparable 協(xié)議江兢,因?yàn)椴⒉皇撬械念愋投季哂小翱杀刃浴?
5.map昨忆、filter、reduce 的作用
  • map 是Array類的一個(gè)方法杉允,我們可以使用它來對數(shù)組的每個(gè)元素進(jìn)行轉(zhuǎn)換
let intArray = [1, 3, 5]
let stringArr = intArray.map {
            return "\($0)"
        }
// ["1", "3", "5"]
  • filter 用于選擇數(shù)組元素中滿足某種條件的元素
let filterArr = intArray.filter {
    return $0 > 1
}
//[3, 5]
  • reduce 把數(shù)組元素組合計(jì)算為一個(gè)值
let result = intArray.reduce(0) {
    return $0 + $1
}
//9
6.map 與 flatmap 的區(qū)別
  • map 可以對一個(gè)集合類型的所有元素做一個(gè)映射操作
  • 和map 不同邑贴,flatmap 有兩個(gè)定義,分別是:
func flatMap(transform: (Self.Generator.Element) throws -> T?) -> [T]
func flatMap(transform: (Self.Generator.Element) -> S) -> [S.Generator.Element]
let intArray = [1, 2, 3, 4]
result = intArray.flatMap { $0 + 2 }
// [3,4,5,6]
對數(shù)組進(jìn)行flatmap操作叔磷,和map是沒有區(qū)別的

1) 第一種情況返回值類型是 T?, 實(shí)際應(yīng)用中拢驾,可以用來過濾元素為nil的情況,(內(nèi)部使用了 if-let 來對nil值進(jìn)行了過濾) 例如:

let optionalArray: [String?] = ["AA", nil, "BB", "CC"];
var optionalResult = optionalArray.flatMap{ $0 }
// ["AA", "BB", "CC"]
操作前是[String?], 操作后會(huì)變成[String]

2) 第二種情況可以進(jìn)行“降維”操作

let numbersCompound = [[1,2,3],[4,5,6]];
var res = numbersCompound.map { $0.map{ $0 + 2 } }
// [[3, 4, 5], [6, 7, 8]]
var flatRes = numbersCompound.flatMap { $0.map{ $0 + 2 } }
// [3, 4, 5, 6, 7, 8]

0.map{0 + 2 } 會(huì)得到[3, 4, 5], [6, 7, 8], 然后遍歷這兩個(gè)數(shù)組改基,將遍歷的元素拼接到一個(gè)新的數(shù)組內(nèi)繁疤,最終并返回就得到了[3, 4, 5, 6, 7, 8]

7.什么是 copy on write

copy on write, 寫時(shí)復(fù)制,簡稱COW寥裂,它通過淺拷貝(shallow copy)只復(fù)制引用而避免復(fù)制值嵌洼;當(dāng)?shù)拇_需要進(jìn)行寫入操作時(shí),首先進(jìn)行值拷貝封恰,在對拷貝后的值執(zhí)行寫入操作,這樣減少了無謂的復(fù)制耗時(shí)褐啡。

應(yīng)用場景 :

寫時(shí)復(fù)制最擅長的是并發(fā)讀取場景诺舔,即多個(gè)線程/進(jìn)程可以通過對一份相同快照,去處理實(shí)效性要求不是很高但是仍然要做的業(yè)務(wù)(比如實(shí)現(xiàn)
FS\DB備份、日志低飒、分析)
適用于對象空間占用大许昨,修改次數(shù)少,而且對數(shù)據(jù)實(shí)效性要求不高的場景

參考:Copy-on-write的介紹與應(yīng)用

8.如何獲取當(dāng)前代碼的函數(shù)名和行號
  • 獲取函數(shù)名: #function
  • 獲取行號:#line
  • 獲取文件名: #file
  • 獲取列:#column
9.如何聲明一個(gè)只能被類 conform 的 protocol

協(xié)議的繼承列表中褥赊,通過添加 class 關(guān)鍵字來限制協(xié)議只能被類類型遵循糕档,而結(jié)構(gòu)體或枚舉不能遵循該協(xié)議。class 關(guān)鍵字必須第一個(gè)出現(xiàn)在協(xié)議的繼承列表中拌喉,在其他繼承的協(xié)議之前:

protocol SomeClassOnlyProtocol: class, SomeInheritedProtocol {
    // 這里是類類型專屬協(xié)議的定義部分
}
10.guard 使用場景

使用 guard 來表達(dá) “提前退出”的意圖速那,有以下使用場景

  • 在驗(yàn)證入口條件時(shí)
  • 在成功路徑上提前退出
  • 在可選值解包時(shí)(拍扁 if let..else 金字塔)
  • return 和 throw 中
  • 日志、崩潰和斷言中
    而下面則是盡量避免使用的場景:
  • 不要用 guard :替代瑣碎的 if..else 語句
  • 不要用 guard :作為 if 的相反情況
  • 不要:在 guard 的 else 語句中放入復(fù)雜代碼
    具體參見 使用 guard 的正確姿勢
11.defer 使用場景

defer 語句用于在退出當(dāng)前作用域之前執(zhí)行代碼.例如:
手動(dòng)管理資源時(shí)尿背,比如 關(guān)閉文件描述符端仰,或者即使拋出了錯(cuò)誤也需要執(zhí)行一些操作時(shí),就可以使用 defer 語句田藐。
如果多個(gè) defer 語句出現(xiàn)在同一作用域內(nèi)荔烧,那么它們執(zhí)行的順序與出現(xiàn)的順序相反

func f() {
    defer { print("First") }
    defer { print("Second") }
    defer { print("Third") }
}
f()
// 打印 “Third”
// 打印 “Second”
// 打印 “First”

詳細(xì)講解請參考喵神的文章:關(guān)于 Swift defer 的正確使用

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市汽久,隨后出現(xiàn)的幾起案子鹤竭,更是在濱河造成了極大的恐慌,老刑警劉巖景醇,帶你破解...
    沈念sama閱讀 216,496評論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件诺擅,死亡現(xiàn)場離奇詭異,居然都是意外死亡啡直,警方通過查閱死者的電腦和手機(jī)烁涌,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,407評論 3 392
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來酒觅,“玉大人撮执,你說我怎么就攤上這事∠系ぃ” “怎么了抒钱?”我有些...
    開封第一講書人閱讀 162,632評論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長颜凯。 經(jīng)常有香客問我谋币,道長,這世上最難降的妖魔是什么症概? 我笑而不...
    開封第一講書人閱讀 58,180評論 1 292
  • 正文 為了忘掉前任蕾额,我火速辦了婚禮,結(jié)果婚禮上彼城,老公的妹妹穿的比我還像新娘诅蝶。我一直安慰自己退个,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,198評論 6 388
  • 文/花漫 我一把揭開白布调炬。 她就那樣靜靜地躺著语盈,像睡著了一般。 火紅的嫁衣襯著肌膚如雪缰泡。 梳的紋絲不亂的頭發(fā)上刀荒,一...
    開封第一講書人閱讀 51,165評論 1 299
  • 那天,我揣著相機(jī)與錄音棘钞,去河邊找鬼缠借。 笑死,一個(gè)胖子當(dāng)著我的面吹牛武翎,可吹牛的內(nèi)容都是我干的烈炭。 我是一名探鬼主播,決...
    沈念sama閱讀 40,052評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼宝恶,長吁一口氣:“原來是場噩夢啊……” “哼符隙!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起垫毙,我...
    開封第一講書人閱讀 38,910評論 0 274
  • 序言:老撾萬榮一對情侶失蹤霹疫,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后综芥,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體丽蝎,經(jīng)...
    沈念sama閱讀 45,324評論 1 310
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,542評論 2 332
  • 正文 我和宋清朗相戀三年膀藐,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了屠阻。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,711評論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡额各,死狀恐怖国觉,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情虾啦,我是刑警寧澤麻诀,帶...
    沈念sama閱讀 35,424評論 5 343
  • 正文 年R本政府宣布,位于F島的核電站傲醉,受9級特大地震影響蝇闭,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜硬毕,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,017評論 3 326
  • 文/蒙蒙 一呻引、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧昭殉,春花似錦苞七、人聲如沸藐守。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,668評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至乾蓬,卻和暖如春惠啄,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背任内。 一陣腳步聲響...
    開封第一講書人閱讀 32,823評論 1 269
  • 我被黑心中介騙來泰國打工撵渡, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人死嗦。 一個(gè)月前我還...
    沈念sama閱讀 47,722評論 2 368
  • 正文 我出身青樓趋距,卻偏偏與公主長得像,于是被迫代替她去往敵國和親越除。 傳聞我的和親對象是個(gè)殘疾皇子节腐,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,611評論 2 353

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