在WWDC2015上,蘋果工程師Doug Gregor和Bill Dudney 評價 了Swift對值類型的支持,並解釋了如何通過它實現一種靈活的不可變性,以構建更好的應用。
Gregor首先評價了Objective-C中常用的引用語義。引用語義的主要問題在於它有可能產生預期之外的對象共享行為,這種行為有可能導致 對象的屬性 被暗中改動。Objective-C程序員對此已經十分了解了,因為許多Cocoa和Cocoa Touch類,像NSString、NSURLRequest,以及所有的集合調用時都需要拷貝。所以為了讓程序員更易於進行防御性的拷貝,Objective-C語言甚至為屬性提供了一個copy特性,當給一個給定的屬性分配對象時,運行時本身就會拷貝一個副本。
對於性能和內存的使用來說,防御性拷貝明顯不是最優的措施,尤其在使用不當時更可能造成微妙的問題。
隨後,Gregor繼續探索不可變性是否是這個問題的正確答案。許多Cocoa類,像NSDate、NSURL、UIImage、 NSNumber和其它許多類都強制實施不可變性。根據Gregor的評價,不可變性擁有許多優點,比如沒有副作用和可共享,但它也會生成尴尬的接口,並且不能有效地映射到機器模型。為了具體說明這一點,Gregor在Haskell和Swift中分別運行Eratosthenes篩法來舉例說明不可變性是如何犧牲性能的。
根據Gregor的評價,對值語義的使用正是這類問題的解決辦法,而Swift完全支持這種值語義:
值類型僅僅就是值,並且它們是不可變的。它們沒有標識符,所以只能以值來區分。這就需要所有的值類型都遵守Equatable協議。
protocol Equatable {
/// Reflexive - `x == x` is `true`
/// Symmetric - `x == y` then `y == x`
/// Transitive - `x == y` and `y == z` then `x == z`
func ==(lhs:Self, rhs:Self) -> Bool
}
此外,值類型允許應用程序根據需要在可變性和不可變性之間取得適當的平衡。Gregor表示:實際上,你可以對值類型使用let關鍵字,以指定一個不會改變的變量,或者使用var來指定一個可以在不影響其它值的前提下更新自身的值的變量。
let numbers = [1, 2, 3, 4]
var strings = [String]()
for x in numbers {
strings.append(String(x))
}
如前文所述,值類型是不可變的,所以它們只能被拷貝。但是,Gregor說,它們的拷貝操作開銷很低,對於簡單的值類型,比如Int、 Double、CGPoint等,它們的拷貝時間是個常數。對於可擴展的數據結構,將會使用寫時拷貝(copy-on-write)技術,只有當值改變時,才會建立一個副本,所以這種技術比默認拷貝方式更有效率。
此次演講的第二部分專注於提供一個使用Swift值類型進行編程的動手實驗示例。
Apple Swift學習教程 http://www.linuxidc.com/Linux/2014-09/106420.htm
使用 Swift 構建一個 iOS 的郵件應用 http://www.linuxidc.com/Linux/2014-08/105542.htm
Swift 2.0開源化 http://www.linuxidc.com/Linux/2015-06/118594.htm
Swift 的詳細介紹:請點這裡
查看英文原文: Building Better Swift Apps Using Value Types