Swift的面試問題及答案-part2

譯文:Swift Interview Questions and Answers

Swift面試問題及答案-part2

原文鏈接 : Swift Interview Questions and Answers
譯文發(fā)布地址:
part1: http://www.itdecent.cn/p/e98d7dc625ff
part2:http://www.itdecent.cn/p/0b9bdffc2523
原文作者 : Antonio Bello
譯者 : lfb_CD
歡迎關(guān)注我的微博:http://weibo.com/lfbWb

寫在前面的話:

譯文中有許多鏈接和代碼是我為方便讀者閱讀添加的---我可是一名有情懷的譯者


Verbal questions 口頭的提問

到達(dá)這一步你已經(jīng)很優(yōu)秀了,但是你還不能自稱為絕地武士(意思是還不能認(rèn)為自己很厲害了)任何人只要夠努力都可以解決上面那些代碼,但是你如何處理下面這些不斷出現(xiàn)的理論知識和實(shí)踐問題呢
回答這些問題仍然需要你在Playground里實(shí)際操作

初級

Question #1 - Swift 1.0 or later

什么是可選數(shù)據(jù)類型?它解決了什么問題?

答案:

可選數(shù)據(jù)類型是用來表示一個數(shù)據(jù)類型缺少具體值。在Objective-C中,只有引用類型才允許沒有具體值,用的是nil來表示。比如float數(shù)據(jù)類型沒有這樣的特性

Swift用可選數(shù)據(jù)類型擴(kuò)展了值類型和引用數(shù)據(jù)類型??蛇x數(shù)據(jù)類型任何時(shí)候都允許擁有具體值或者為nil

Question #2 - Swift 1.0 or later

什么時(shí)候使用結(jié)構(gòu)體,我們什么時(shí)候又應(yīng)該使用類呢?

答案:

有一個正在進(jìn)行的討論,關(guān)于過度使用類超過結(jié)構(gòu)體這究竟是好還是壞。
函數(shù)式編程傾向于多使用值數(shù)據(jù)類型,而面向?qū)ο缶幊谈鼉A向于使用類。
在Swift中,類和結(jié)構(gòu)體有很多不同的特性??梢缘贸鱿旅孢@樣一份總結(jié):

  • 類支持繼承,結(jié)構(gòu)體不行
  • 類是引用類型,結(jié)構(gòu)體是值類型

我們并沒有一個規(guī)則來判定使用哪一個是最好。一般的建議是在能夠達(dá)到你目標(biāo)的前提下且使用到的代價(jià)最小(結(jié)構(gòu)體比類節(jié)省內(nèi)存空間)。除非你需要用到繼承或者是引用的語法,否則那就采用結(jié)構(gòu)體。

更多關(guān)于類和結(jié)構(gòu)體的細(xì)節(jié)問題請查閱這篇文章:
detailed post on the matter.(我們還在翻譯中..)

注意:在運(yùn)行時(shí),結(jié)構(gòu)體比類具有更高性能的因?yàn)榻Y(jié)構(gòu)體的方法調(diào)用是靜態(tài)綁定的,而類的方法調(diào)用是在運(yùn)行時(shí)動態(tài)解析。這是另一個很好的理由來使用結(jié)構(gòu)體,而不是使用類。

Question #3 - Swift 1.0 or later

什么是泛型,它們又解決了什么問題?

答案:

泛型是用來使代碼能安全工作。在Swift中,泛型可以在函數(shù)數(shù)據(jù)類型和普通數(shù)據(jù)類型中使用,例如類、結(jié)構(gòu)體或枚舉。

泛型解決了代碼復(fù)用的問題。有一種常見的情況,你有一個方法,需要一個類型的參數(shù),你為了適應(yīng)另一種類型的參數(shù)還得重新再寫一遍這個方法。
比如,在下面的代碼中,第二個方法是第一個方法的“克隆體”:

func areIntEqual(x: Int, _ y: Int) -> Bool {
return x == y
}
func areStringsEqual(x: String, _ y: String) -> Bool {
return x == y
}
areStringsEqual("ray", "ray") // true
areIntEqual(1, 1) // true

>一個Objective-C開發(fā)者可能會采用`NSObject`來解決問題:
>

import Foundation
func areTheyEqual(x: NSObject, _ y: NSObject) -> Bool {
return x == y
}
areTheyEqual("ray", "ray") // true
areTheyEqual(1, 1) // true

>這段代碼能達(dá)到了目的,但是編譯的時(shí)候并不安全。它允許一個字符串和一個整型數(shù)據(jù)進(jìn)行比較:
>

areTheyEqual(1, "ray")

程序可能不會崩潰,但是允許一個字符串和一個整型數(shù)據(jù)進(jìn)行比較可能不會得到想要的結(jié)果。
采用泛型的話,你可以將上面兩個方法合并為一個,并同時(shí)還保證了數(shù)據(jù)類型安全。這是實(shí)現(xiàn)代碼:
>

func areTheyEqual<T: Equatable>(x: T, _ y: T) -> Bool {
return x == y
}
areTheyEqual("ray", "ray")
areTheyEqual(1, 1)


### Question #4 - Swift 1.0 or later
偶爾你也會不可避免地使用隱式可選類型。那請問什么時(shí)候我們需要這么做?為什么需要這么做?
>#### 答案:
>最常見的情況是:

>>1. 不為nil的才能初始化它的值。一個典型的例子是一個界面生成器的出口(Interface Builder outlet),它總是在它的本體初始化后初始化。在這種情況下,如果它在界面構(gòu)建器(Interface Builder)中正確地配置了,就能夠保證在使用前outlet不為nil的。
>>
>>2.為解決強(qiáng)引用循環(huán)問題(不知道循環(huán)引用是什么的可以看我們翻譯的Swift官方文檔[自動引用計(jì)數(shù)篇](http://wiki.jikexueyuan.com/project/swift/chapter2/16_Automatic_Reference_Counting.html))。當(dāng)2個實(shí)例互相引用時(shí),就需要一個不為nil的引用指向另一個實(shí)例。引用的一邊可以修飾為unowned,另一邊使用隱式可選類型,便可解決循環(huán)引用問題。
>>為方便大家理解我貼段代碼上來(原文是沒用的)

>>```
class Customer {
    let name: String
    var card: CreditCard?
    init(name: String) {
        self.name = name
    }
    deinit { print("\(name) is being deinitialized") }
}
class CreditCard {
    let number: UInt64
    unowned let customer: Customer
    init(number: UInt64, customer: Customer) {
        self.number = number
        self.customer = customer
    }
    deinit { print("Card #\(number) is being deinitialized") }
}

理解得不太清楚可以點(diǎn)開上面鏈接查看

小貼士:盡量不要使用隱式可選類型。使用它們會增加運(yùn)行時(shí)崩潰的幾率。在某些情況下,出現(xiàn)崩潰也許是程序員需要這么做,這里也有一個更好的方法來達(dá)到同樣的效果,例如,使用fatalerror()。

Question #5 - Swift 1.0 or later

你知道有哪些解包的方式?它們是否是安全解包的?

答案:

ps:下面代碼為譯者本人為方便讀者閱讀而添加,如還有不理解的地方可以根據(jù)關(guān)鍵字搜索相關(guān)文檔

  • 強(qiáng)制用!展開 -- 操作不安全

  • 聲明隱式可選類型變量 -- 在許多情況下是不安全的

(var implicitlyUnwrappedString: String!)

>* optional binding --  安全
>
>   ```
var count: Int?
count = 100
if let validCount = count {
    "count is " + String(validCount)    //count is 100
} else {
    "nil"
}
  • 新的Swift2 guard聲明 -- 安全

  • 自判斷鏈接--安全

if let roomCount = john.residence?.numberOfRooms {
println("John's residence has (roomCount) room(s).")
} else {
println("Unable to retrieve the number of rooms.")
}

>* nil -- 安全

## 中級

漸漸地你挑戰(zhàn)了這里。也許你之前問題解決得很好,但是讓我們看看你是否能很好地通過下面這些問題。

### Question #1 - Swift 1.0 or later
Swift是一種面向?qū)ο蟮恼Z言還是一種面向函數(shù)的語言?
>#### 答案:
Swift是一種混合語言,同時(shí)支持這兩種范式。

>它實(shí)現(xiàn)了三種面向?qū)ο蟮幕驹瓌t
>
* 封裝
* 繼承
* 多態(tài)
>
當(dāng)Swift作為一種面向函數(shù)的語言來理解時(shí),會有不同卻相似的方式來定義它。
其中一種是較為常見的維基百科上的:"…a programming paradigm [...] that treats computation as the evaluation of mathematical functions and avoids changing-state and mutable data."
“……編程范式[……],將數(shù)學(xué)函數(shù)作為一種值,不需要考慮其中的狀態(tài)變化和數(shù)據(jù)變化。”

>你要覺得Swift是一個門成熟的面向函數(shù)的編程語言是比較牽強(qiáng)的,但它確實(shí)也具有很多面向函數(shù)編程的基本要素。

### Question #2 - Swift 1.0 or later
下列哪些特性是Swift含有的?

1. 泛型類
2. 泛型結(jié)構(gòu)
3. 泛型接口

>#### 答案:
>* Swift中包括了上述的1和2。泛型可以在類,結(jié)構(gòu)體,枚舉全局方法或者普通方法中使用。
>* 3用typealias實(shí)現(xiàn)了。它本身不是一個泛型類型,它是一個占位符名稱。它通常被稱為關(guān)聯(lián)類型,當(dāng)一個協(xié)議聲明時(shí)使用。如果有不明白的可查看[喵神的文章](http://swifter.tips/typealias/)

### Question #3 - Swift 1.0 or later
在Objective-C語言中,常量可以被定義如下:

const int number = 0;

這是Swift對應(yīng)的代碼:

let number = 0

請問它們有什么區(qū)別么?如果有,你能解釋下它們之間的區(qū)別么?
>#### 答案:
`const` 是一個變量在編譯時(shí)初始化的值或著是在編譯時(shí)解決初始化的。
>
`let`聲明的常數(shù)是在運(yùn)行的時(shí)候創(chuàng)建,它最終可以被初始化為靜態(tài)或者動態(tài)的表達(dá)式。注意它的值只能被分配一次。

### Question #4 - Swift 1.0 or later
Swift聲明一個靜態(tài)屬性或靜態(tài)函數(shù)可以使用static來修飾。這是一個結(jié)構(gòu)體的例子:

struct Sun {
static func illuminate() {}
}

對于類,可以使用static或class來修飾。他們可以達(dá)到同樣的目標(biāo),但實(shí)際上他們是不同的。你能解釋他們有什么不同嗎?
>#### 答案:
使用static聲明的一個靜態(tài)屬性或者方法并不可被覆蓋override(子類覆蓋父類的方法)。
使用class就可以覆蓋。
>
當(dāng)用在類里的時(shí)候,static相當(dāng)于class final
比如在下面這段代碼中你如果覆蓋`illuminate()`編譯器就會報(bào)錯
>

class Star {
class func spin() {}
static func illuminate() {}
}
class Sun : Star {
override class func spin() {
super.spin()
}
override static func illuminate() { // error: class method overrides a 'final' class method
super.illuminate()
}
}


### Question #5 - Swift 1.0 or later
可以使用擴(kuò)展添加存儲屬性嗎?

>#### 答案:
no,這是不可能的。擴(kuò)展可以為已經(jīng)存在的數(shù)據(jù)類型添加新的行為,但是不允許改變類型本身或它的接口。
如果您添加了存儲的屬性,您需要額外的內(nèi)存來存儲新的值。擴(kuò)展不能完成這樣的任務(wù)。

##高級
噢,孩子,你是個聰明的人,對嗎?那就一步一步向上攀爬吧。

### Question #1 - Swift 1.2 or later
在Swift1.2中,你可以解釋一下聲明一個枚舉類型的泛型的問題么?

以一個含有兩個泛型參數(shù)`T`和`V`的枚舉`Either`為例,用`T`作為`Left`的相關(guān)值類型,`V`作為`Right`的相關(guān)值類型:

enum Either<T, V> {
case Left(T)
case Right(V)
}

小貼士:檢查這種情況應(yīng)該在一個Xcode中的項(xiàng)目中,不是在Playground上。還得注意,這個問題是Swift 1.2相關(guān)的,所以你需要Xcode 6.4。

>#### 答案:
編譯失敗的錯誤消息:
>

unimplemented IR generation feature non-fixed multi-payload enum layout

出現(xiàn)的問題是,不能確定`T`需要的內(nèi)存大小。分配內(nèi)存大小時(shí)取決于`T`本身的數(shù)據(jù)類型,枚舉需要一個可知的固定大小的值類型。
>
最常用的解決方法是把泛型用引用類型進(jìn)行包裝,一般起名為`Box`,代碼如下:
>

class Box<T> {
let value: T
init(_ value: T) {
self.value = value
}
}
enum Either<T, V> {
case Left(Box<T>)
case Right(Box<V>)
}

這個問題只在Swift 1.0或者以上出現(xiàn),但是2.0已經(jīng)解決了。

### Question #2 - Swift 1.0 or later
閉包是值類型還是引用類型的?
>#### 答案:
閉包是引用類型。如果一個閉包被分配給一個變量,該變量被復(fù)制到另一個變量,它們實(shí)際是引用的相同一個閉包并且它里面的參數(shù)列表也同樣會被復(fù)制。

### Question #3 - Swift 1.0 or later
`UInt`數(shù)據(jù)類型用于存儲整數(shù)。它實(shí)現(xiàn)了從一個帶符號的整數(shù)轉(zhuǎn)化為`UInt`的初始化方式:

init(_ value: Int)

然而,如果您提供了一個負(fù)值,例如下面的代碼會產(chǎn)生一個編譯錯誤:

let myNegative = UInt(-1)

我們知道負(fù)數(shù)在內(nèi)部是使用補(bǔ)碼表示,你怎么才能把一個負(fù)數(shù)的`Int`轉(zhuǎn)化為`UInt`,同時(shí)保持它在內(nèi)存中的表示形式?

>#### 答案:
這兒有一個初始化的方式:
>

UInt(bitPattern: Int)


### Question #4 - Swift 1.0 or later
你能描述一下你用Swift時(shí)遇到的循環(huán)引用么?你是怎么解決的?
>#### 答案:
循環(huán)引用是指兩個實(shí)例彼此強(qiáng)引用,導(dǎo)致內(nèi)存泄漏,因?yàn)閮蓚€實(shí)例都不會被收回。原因是只要有一個強(qiáng)引用,實(shí)例就不會被回收。你可以通過 `weak` 或者 `unowned` 引用 替換其中一個強(qiáng)引用,從而打破強(qiáng)引用循環(huán)
>
想了解更多可以查看我們翻譯的Swift官方文檔里的有關(guān)章節(jié)[自動引用計(jì)數(shù)篇](http://wiki.jikexueyuan.com/project/swift/chapter2/16_Automatic_Reference_Counting.html)

### Question #5 - Swift 2.0 or later
Swift2.0增添了一個新關(guān)鍵字實(shí)現(xiàn)遞歸枚舉。這里有一個枚舉包含一個`Node`,`Node`有兩個的相關(guān)的值類型,`T`和`List`:

enum List<T> {
case Node(T, List<T>)
}

請問那個可以實(shí)現(xiàn)遞歸枚舉的關(guān)鍵字是什么?
>#### 答案:
>
`indirect`
>
代碼如下:
>

enum List<T> {
indirect case Cons(T, List<T>)
}


# 之后的方向?
恭喜你看到了文章末尾,如果你確實(shí)不太清楚那些答案,希望你也不要感到沮喪!

其中的一些問題很復(fù)雜,Swift是一個非常豐富、且富有表現(xiàn)力的語言。我們還有很多需要學(xué)。此外,蘋果不斷改善Swift與添加新的功能,所以非常有可能還存在一些非常好用的但是我們并不知道的(言外之意就是讓我們多研究)。

To get to know Swift or build upon what you already know, be sure to check out our in-depth, tutorial-rich book, [Swift by Tutorials](http://www.raywenderlich.com/store/swift-by-tutorials), or sign up for our hands-on tutorial conference [RWDevCon](http://www.rwdevcon.com/)!


當(dāng)然,最根本的資料當(dāng)然還是由蘋果公司寫撰寫的[The Swift Programming Language](https://developer.apple.com/library/ios/documentation/Swift/Conceptual/Swift_Programming_Language/) (ps:肯定還有我們翻譯的[Swift中文版](http://wiki.jikexueyuan.com/project/swift/)撒!)

最后,使用一門語言才是學(xué)習(xí)語言最好的方式。只需要你在Playground上寫寫或在一個真正的項(xiàng)目使用Swift。Swift幾乎可以與objective-c無縫地混合,所以建立一個你已經(jīng)非常熟悉的現(xiàn)有項(xiàng)目是一個很好的方法來學(xué)習(xí)Swift的來龍去脈。

感謝您的閱讀和解決以上這些問題所做出的努力!你也可以在評論中留下你的問題或者一些你的發(fā)現(xiàn)。我也不介意你提出一些你項(xiàng)目中遇到的問題。我們可以互相學(xué)習(xí)。咱們論壇上見!

***
第一次翻譯這么長的文章,也許會有翻譯錯誤的地方,大家可以在評論中幫忙指出。

另外,我在管理一個微信公眾號SwiftTips,每天發(fā)布一些Swift的文章什么的,歡迎關(guān)注
![qrcode_for_gh_e36203f1d8d6_258.jpg](http://upload-images.jianshu.io/upload_images/40785-18a32b6e9b5e5eb6.jpg?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 譯文:Swift Interview Questions and Answers Swift面試問題及答案 原文鏈...
    lfb_CD閱讀 8,569評論 11 111
  • 發(fā)現(xiàn) 關(guān)注 消息 iOS 第三方庫、插件、知名博客總結(jié) 作者大灰狼的小綿羊哥哥關(guān)注 2017.06.26 09:4...
    肇東周閱讀 15,088評論 4 61
  • 136.泛型 泛型代碼讓你可以寫出靈活,可重用的函數(shù)和類型,它們可以使用任何類型,受你定義的需求的約束。你可以寫出...
    無灃閱讀 1,655評論 0 4
  • 搞笑給別人笑的人其實(shí)內(nèi)心都是抑郁的。說起這個,想到星爺,肥姐,諸如此類人等。 這樣的舉例似乎很沒有邏輯。 莫急,且...
    蘭嵐Lillian閱讀 290評論 0 0
  • 食材:芹菜,豬舌,八角,桂皮,姜片,蔥花 調(diào)料: 生抽,鹽,蠔油 做法: 1,芹菜洗凈切段備用 2,豬舌用開水燙一...
    蘊(yùn)含精華閱讀 1,079評論 0 0

友情鏈接更多精彩內(nèi)容